admin管理员组

文章数量:1289505

I'm getting a "TypeError: Cannot read property 'map' of undefined". Not sure where I'm going wrong on this. I'm still pretty new when it es to React so I don't know if I am missing something or not. It's giving me the error when I'm trying to call this.props.meals.map

export class Dashboard extends React.Component {
  ponentDidMount() {
    this.props.dispatch(fetchProtectedData());
    this.props.dispatch(retrieveDailyLogs())
    .then(results => {
        return this.props.dispatch(getDailyLogs(results));
    })
}

getId(id) {
   console.log('test');
   this.props.dispatch(removeDay(id))
   this.props.dispatch(retrieveDailyLogs())
  .then(results => {
    return this.props.dispatch(getDailyLogs(results));
});
}


render() {
    const dailyLogs = this.props.meals.map((day, index) => 
    <li className="card" key={index}>
        <Card handleClick={(id) => this.getId(id)} {...day} />
    </li>
    )
    return (
        <section className="dashboard-container">
            <h1>Dashboard</h1>
            <Link className="log-day-btn" to="/dailylogs">Log Meals</Link>
            <ul className="meal-list">
            {dailyLogs}
            </ul>
        </section>
    );
}
}

const mapStateToProps = state => ({
  meals: state.dailyLogsReducer.dailyLogs
});

export default requiresLogin()(connect(mapStateToProps)(Dashboard));

Here is my reducer just in case this might help

import {ADD_DAY, GET_DAILYLOGS, DELETE_DAY} from '../actions/dailyLogs';

const initialState = {
 dailyLogs: [{
    date: null,
    meal1: null,
    meal2: null,
    meal3: null,
    snack: null,
    totalCalories: null,
}]
};

export default function reducer(state = initialState, action) {
 if (action.type === ADD_DAY) {
    return Object.assign({}, state, {
        dailyLogs: [...state.dailyLogs, {
            date: action.date,
            meal1: action.meal1,
            meal2: action.meal2,
            meal3: action.meal3,
            snack: action.snack,
            totalCalories: action.totalCalories
        }]
    });
}
else if(action.type === GET_DAILYLOGS) {
    return Object.assign({}, state, {
            dailyLogs: action.dailyLogs.dailyLogs
    })
}
else if(action.type === DELETE_DAY) {
    return 'STATE';
}
return state;
}

Here is my bineReducer. It is in my store.js

bineReducers({
    form: formReducer,
    auth: authReducer,
    protectedData: protectedDataReducer,
    dailyLogsReducer
}),

I'm getting a "TypeError: Cannot read property 'map' of undefined". Not sure where I'm going wrong on this. I'm still pretty new when it es to React so I don't know if I am missing something or not. It's giving me the error when I'm trying to call this.props.meals.map

export class Dashboard extends React.Component {
  ponentDidMount() {
    this.props.dispatch(fetchProtectedData());
    this.props.dispatch(retrieveDailyLogs())
    .then(results => {
        return this.props.dispatch(getDailyLogs(results));
    })
}

getId(id) {
   console.log('test');
   this.props.dispatch(removeDay(id))
   this.props.dispatch(retrieveDailyLogs())
  .then(results => {
    return this.props.dispatch(getDailyLogs(results));
});
}


render() {
    const dailyLogs = this.props.meals.map((day, index) => 
    <li className="card" key={index}>
        <Card handleClick={(id) => this.getId(id)} {...day} />
    </li>
    )
    return (
        <section className="dashboard-container">
            <h1>Dashboard</h1>
            <Link className="log-day-btn" to="/dailylogs">Log Meals</Link>
            <ul className="meal-list">
            {dailyLogs}
            </ul>
        </section>
    );
}
}

const mapStateToProps = state => ({
  meals: state.dailyLogsReducer.dailyLogs
});

export default requiresLogin()(connect(mapStateToProps)(Dashboard));

Here is my reducer just in case this might help

import {ADD_DAY, GET_DAILYLOGS, DELETE_DAY} from '../actions/dailyLogs';

const initialState = {
 dailyLogs: [{
    date: null,
    meal1: null,
    meal2: null,
    meal3: null,
    snack: null,
    totalCalories: null,
}]
};

export default function reducer(state = initialState, action) {
 if (action.type === ADD_DAY) {
    return Object.assign({}, state, {
        dailyLogs: [...state.dailyLogs, {
            date: action.date,
            meal1: action.meal1,
            meal2: action.meal2,
            meal3: action.meal3,
            snack: action.snack,
            totalCalories: action.totalCalories
        }]
    });
}
else if(action.type === GET_DAILYLOGS) {
    return Object.assign({}, state, {
            dailyLogs: action.dailyLogs.dailyLogs
    })
}
else if(action.type === DELETE_DAY) {
    return 'STATE';
}
return state;
}

Here is my bineReducer. It is in my store.js

bineReducers({
    form: formReducer,
    auth: authReducer,
    protectedData: protectedDataReducer,
    dailyLogsReducer
}),
Share Improve this question edited Sep 13, 2018 at 6:43 Hyyan Abo Fakher 3,5273 gold badges24 silver badges36 bronze badges asked Sep 12, 2018 at 22:32 D.GravesD.Graves 1892 silver badges12 bronze badges 5
  • 3 it's saying that this.props.meals is undefined - and this can only mean that you didn't pass in any meals prop when you rendered <Dashboard/>. Can't see where you are doing that in order to check, but there can be no other explanation. – Robin Zigmond Commented Sep 12, 2018 at 22:35
  • Okay see I thought I was doing that with the mapStateToProps down at the bottom. Would seeing my dailyLogsReducer help? – D.Graves Commented Sep 12, 2018 at 22:55
  • Sorry, I missed that @D Graves. I'm afraid that I've only dabbled with React, and never used Redux (although I have read the docs for it not too long ago), so this is a little bit over my head at the moment. One thing I will say, having just quickly checked again, is that a "reducer" is supposed to be a function (which takes a state and an action and returns a new state), so I am not sure how your dailyLogsReducer has a dailyLogs property. And if it doesn't, that would explain why your meals prop is undefined. Hopefully someone more knowledgeable than me will be able to help! – Robin Zigmond Commented Sep 12, 2018 at 23:12
  • Sharing your reducer and if you bine a few of them, your bine reducer config definitely will help. Also, is this data ing from via an async operation? – devserkan Commented Sep 12, 2018 at 23:25
  • Can you track your state somehow with Redux Dev Tools? It is very useful, consider using it. Try to log your state in this ponent. Instead of opening one state, just open your whole state like: const mapStateToProps = state => ({ state }); Then try to log it console.log(this.props.state); – devserkan Commented Sep 12, 2018 at 23:47
Add a ment  | 

2 Answers 2

Reset to default 9

The render method can run before ponentDidMount does. If this.props.meals is not yet defined by the time the render method runs, your ponent will throw the error you're seeing.

You can check against its presence before mapping through the object with

this.props.meals && this.props.meals.map( // your code here )

Since you declarated dailyLogs in your reducer's initialState as an array, your map should not fail, but only would show us nothing if the data was there. If data is obtained by a async operation, you cant ensure that this data will be there at the rendering moment did by React.

So, we have some points here:

Ensure you won't receive any errors because you tried to use non-undefined operation into a undefined value:

const dailyLogs = this.props.meals  
console.log("meals =", dailyLogs); // Will help you know what is this value.
dailyLogs ? dailyLogs.map((day, index) => 
  <li className="card" key={index}>
    <Card handleClick={(id) => this.getId(id)} {...day} />
  </li> : // handle the non-mappable value ...
)

In your reducer, as a good practice, try to use the switch case statement to explore his benefits

switch (action.type) {
   case ADD_DAY: 
       return // ...
   case GET_DAILYLOGS:
       return // ...
   case DELETE_DAY: 
       return // ...
   default: 
       return state;
}

And in your switch or if/else statements return, you can do as follows to evolve the state keeping his actuals attributes (spreading):

return { 
    ...state, 
    dailyLogs: [
    // ...
    ]
};

Keep your code cleaner and concise will help you at all.

Hope it helps someway.

本文标签: javascriptTypeError Cannot read property 39map39 of undefined using ReactJsStack Overflow