react js mapStateToProps triggers Uncaught TypeError: Cannot read property 'map' of undefined

帅比萌擦擦* 提交于 2019-12-20 03:09:10

问题


I have an index.js which renders all tables in the database.

_renderAllTables() {
const { fetching } = this.props;

let content = false;

if(!fetching) {
  content = (
    <div className="tables-wrapper">
      {::this._renderTables(this.props.allTables)}
    </div>
    );
}

return (
  <section>
    <header className="view-header">
      <h3>All Tables</h3>
    </header>
    {content}
  </section>
);
}

_renderTables(tables) {

return tables.map((table) => {
  return <Table
            key={table.id}
            dispatch={this.props.dispatch}
            {...table} />;               
});
}

render() {
return (
  <div className="view-container tables index">
    {::this._renderAllTables()}
  </div>
  );
 }
}
const mapStateToProps = (state) => (
  state.tables);

export default connect(mapStateToProps)(HomeIndexView);

I changed mapStateToProps from above code to below code.

 const mapStateToProps = (state) => ({
tables: state.tables,
currentOrder: state.currentOrder,
});

The reason why I changed code is that I want to use one of state of currentOrder. I have a state which shows whether table is busy or not. So in order to use that I added currentOrder in mapStateToProps. However, it triggers Uncaught TypeError: Cannot read property 'map' of undefined..

How can I use states from other components? any suggestions for that??

Thanks in advance..

--reducer.js

 const initialState = {
  allTables: [],
  showForm: false,
  fetching: true,
  formErrors: null,
   };


  export default function reducer(state = initialState, action = {}) {
   switch(action.type){
    case Constants.TABLES_FETCHING:
        return {...state, fetching: true};

    case Constants.TABLES_RECEIVED:
        return {...state, allTables: action.allTables, fetching: false};

    case Constants.TABLES_SHOW_FORM:
        return {...state, showForm: action.show};

    case Constants.TALBES_RESET:
        return initialState;

    case Constants.ORDERS_CREATE_ERROR:
        return { ...state, formErrors: action.errors };


    default:
        return state;
   }
 }

回答1:


Your problem is that before fetching successfully tables, your component is rendered with state.tables is undefined.

First of all, best practice is to use selectors rather than json path like state.tables, to be in a separate selectors.js file using reselect lib as follow:

import { createSelector } from 'reselect';

const tablesSelector = state => state.tables;

export default {
  tablesSelector,
}

Second, you need to add reducer for, let's assume, FETCH_ALL_TABLES action using combineReducers from redux lib and most important to initialize tables array with [] before the action is dispatched so as to be defined as follow:

import {combineReducers} from 'redux';

function tables(state = [], {type, payload}) {
  switch (type) {
    case 'FETCH_ALL_TABLES':
      return [
        ...state,
        ...payload,
      ]
  }

  return state;
}


export default combineReducers({
  tables,
});

and in your index.js, may be want update it to:

import selector from './selector';

...

function mapStateToProps(state) {
  return {
    tables: selector.tablesSelector(state),
  }
}



回答2:


You should always check if variable you want to map is defined.

_renderTables(tables) {
    if (tables) {
        return tables.map((table) => {
            return <Table
                key={table.id}
                dispatch={this.props.dispatch}
                {...table} />;               
        });
    }
}


来源:https://stackoverflow.com/questions/40586885/react-js-mapstatetoprops-triggers-uncaught-typeerror-cannot-read-property-map

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