mapStateToProps() 在 Redux 应用程序中嵌套状态内的状态?

IT技术 javascript reactjs redux state
2021-05-11 10:40:21

我想弄清楚为什么我正在获取和存储在 state 上的 JSON 数据没有映射到我的组件 props,但console.log()mapStateToProps()函数内 ed时出现我做错了什么,我在这里没有看到?

编辑:显然状态上的属性被映射到组件但嵌套。data从 内登录时mapStateToProps(),必须通过 访问属性state.state.data在此之前(参见reducer),当action.data被记录时,数据按预期显示。没有奇怪的嵌套。也许connect函数有问题?

查看如何在 state 对象中填充 state 属性:

查看状态对象中填充的数据属性

下面是我的组件:

class ViewSelector extends Component {
  componentWillMount() {
    this.props.fetchDataAsync('VIEW ALL');
  }

  selectView(event) {
    // this.props.data comes up undefined despite state being mapped
    // to the component props
    console.log('props: ' + this.props.data);
    this.props.filterData(event.target.innerHTML, this.props.data);
  }

  render() {
    return (
      <section>
        <nav>
          <button onClick={this.selectView.bind(this)}>VIEW ALL</button>
          <button onClick={this.selectView.bind(this)}>VIEW LAST WEEK</button>
          <button onClick={this.selectView.bind(this)}>VIEW LAST MONTH</button>
        </nav>
        <Dashboard data={this.props.data}/>
      </section>
    );
  }
}

function mapStateToProps(state) {
  console.log(state);
  // this console.log shows the state with the data property.
  return {
    data: state.data
  };
}

export default connect(mapStateToProps, actions)(ViewSelector);

编辑:这是用于澄清的减速器:

import {
  FETCH_DATA,
  FETCH_DATA_SUCCESS,
  FETCH_DATA_FAILURE,
  FILTER_DATA
} from '../actions/types';
import { getLastWeek, getLastMonth } from './reducer_helper';

const initialState = {
  error: '',
  loading: false,
  data: []
};

/* eslint-disable */
const app = (state = initialState, action) => {
  switch(action.type) {
    case FETCH_DATA:
      return { ...state, error: '', loading: true };
    case FETCH_DATA_SUCCESS:
      // console.log(action.data) returns data as expected.
      // no nesting...until it hits the mapStateToProps() function
      return { ...state, error: '', loading: false, data: action.data };
    case FETCH_DATA_FAILURE:
      return { ...state, error: action.error, loading: false };
    case FILTER_DATA:
      let data;
      if (action.view === 'VIEW LAST WEEK') {
        data = getLastWeek(state.data);
      } else if (action.view === 'VIEW LAST MONTH') {
        data = getLastMonth(state.data);
      } else {
        data = state.data;
      }
      return { ...state, error: '', loading: false, data };
  }
  return state;
}

export default app;

Action Creators 澄清了对 Reducer 的调度:

export function fetchData() {
  return {
    type: FETCH_DATA
  };
}

export function fetchDataSuccess(data) {
  return {
    type: FETCH_DATA_SUCCESS,
    data: data
  };
}

export function fetchDataFailure(data) {
  return {
    type: FETCH_DATA_FAILURE,
    data
  };
}

export function filterData(view) {
  return {
    type: FILTER_DATA,
    view
  };
}

export function fetchDataAsync() {
  return dispatch => {
    dispatch(fetchData());

    axios.get(DATA_URL)
    .then(res => {
      dispatch(fetchDataSuccess(res.data));
    }).catch(err => {
      dispatch(fetchDataFailure(err));
    });
  };
}

整个应用程序的渲染方式和 Redux 商店:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

import App from './components/app';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <App />
  </Provider>
  , document.querySelector('.container'));
3个回答

经过多次审查、调试和询问其他开发人员,简而言之,这就是我面临的问题:reducer 以及如何将其导入主“清单”文件以管理所有其他 reducer。

基本上,因为我在这个项目中只使用了一个减速器,所以不需要清单减速器文件。见下文:

import { combineReducers } from 'redux';
import Reducer from './reducer';

const rootReducer = combineReducers({
  state: Reducer
});

export default rootReducer;

我不知道为什么这是嵌套状态。也许是因为,理论上,我们将处理多个具有不同目的的 reducer(如数据 reducer 和用户 reducer),并且需要将它们嵌套到我们的状态树中进行管理。

state = {
  // here is one nested reducer with its own properties
  data: {
    type: // somevalue,
    filtered: true
  },
  // here is another
  user: {
    name: // somename,
    password: // somepassword
  }
};

简而言之...请注意您的减速器是如何导入到您的createStore函数中的,以及它是否是唯一使用的减速器,或者是否有多个减速器正在通过各种清单文件运行。

干杯。

所以你的mapStateToPropsvaluedata是返回一个对象。你可能想要这个:

function mapStateToProps(state) {
  console.log(state);
  // this console.log shows the state with the data property.
   return {
     ...state.app
   };
 }

这将使您可以访问data减速器中的字段此外,示例中并不清楚您将如何使用数据,或者其中包含哪些字段。此外,首先,您的reducer 没有初始化为它将使用的字段的空值或空值,这肯定会导致错误。从一个initialState对象开始可能更好

const initialState = {
  error: '',
  loading: false,
  data: []
};

const app = (state=initialState, action) => {
 /* .... */

我遇到了类似的问题mapStateToProps,在第一次渲染时,它会将初始状态嵌套在具有状态键的对象中。当我使用调度方法更新状态时,它会创建另一个键值对。(控制台中的以下条目是当我在 mapStateToProps 函数中控制台日志状态时)。

嵌套的初始状态:
嵌套的初始状态

我在我的 reducer 函数中发布了它,我正在为我的默认情况返回状态。

const initialState = {
    stateprop1: false,
    user_text: "empty",
    };

    const reducer1 = (state = initialState, action)             => {
    switch (action.type) {
        case ACTION_TYPES.SUCCESS:
            return {
                ...state,
                stateprop1: true,
            };
        case ACTION_TYPES.FAILURE:
            return {
                ...state,
                stateprop1: false,
            };
        case ACTION_TYPES.USER_INPUT:
            return {
                ...state,
                user_text: action.payload,
            };
        default:
            return {
                state,
            };
    }
};

相反,如果我在默认情况下传播状态,则不会观察到嵌套行为。

default:
    return {
        ...state,
    };

所以现在如果我在mapStateToProps函数中控制台日志状态我得到

未嵌套的状态:
未嵌套的状态

我希望这有帮助。