mapStateToProps() in Redux app nesting state within state?

烈酒焚心 提交于 2019-12-08 15:50:37

问题


I've hit a wall trying to figure out why the JSON data I'm fetching and storing on state isn't being mapped to my component props, yet appears when console.log()ed from within the mapStateToProps() function. Am I doing something wrong that I'm not seeing here?

EDIT: Apparently the properties on state are being mapped to the component but are nested. The data property, when logged from within mapStateToProps(), has to be accessed via state.state.data. Prior to this (see reducer), when action.data is logged, the data appears as expected. No strange nesting. Perhaps something is wrong with the connect function?

See how there is a state property populated within the state object:

Below is my component:

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);

EDIT: Here is the reducer for clarification:

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 for clarification on dispatches to 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));
    });
  };
}

How the entire app is being rendered & the Redux store:

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'));

回答1:


After much reviewing, debugging and asking other devs, in a nutshell this is the problem I was facing: The reducer and how it was being imported into a main "manifest" file to manage all other reducers.

Basically, since I was only using one reducer in this project, there was no need for a manifest reducer file. See below:

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

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

export default rootReducer;

I don't know exactly why this was nesting state. Perhaps because, theoretically, we would be dealing with multiple reducers with different purposes (like a data reducer and a user reducer) and would need to nest those into our state tree to manage.

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

In short...be mindful of how your reducer is being imported into your createStore function and if it's the only reducer being used or if there's multiple reducers being run through a manifest file of sorts.

Cheers.




回答2:


So your mapStateToProps value of data is returning an object. You probably want this instead:

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

This will give you access to the fields in your data reducer. Also, it's not clear from the example exactly how you will use the data, or what fields are included in it. Also, to start with, your reducer is not initialized to null or empty values for the fields it will use, which can definitely cause errors. Probably better to start with an initialState object:

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

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


来源:https://stackoverflow.com/questions/39695768/mapstatetoprops-in-redux-app-nesting-state-within-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!