Reputation: 13
Redux Dev Tools view Edit: Here is a picture of redux devtools. It is populating state with an array of objects. Anytime I try to access an object in the array I get this error React Error
I have a server that is getting data from yelp when it receives a get request and it sends the response from yelp up to the client.
When I try to access the server response that was called from the getFoodPlans() function, it shows up as state in the redux webtools but says "Cannot find property name of undefined", if you try to access it through props.
If I use an axios call to the endpoint and set local state with the response, I can access all the properties. I have a feeling that it has to do with the server, because if I send the whole businesses object from the server I get the same error with axios where I can't access a property of undefined.
Does this have to do with how I'm sending the data from the server to the client?
Thank you.
Server:
router.get('/food', (req, res) => {
const position = Math.floor(Math.random() * 15);
axios
.get(`${foodSearch}location=kansascity
&&radius=${radius}&&cost=1,2,3&&categories=food`, {
headers: { Authorization: `Bearer ${apiKey}` }
})
.then(result => {
res.json(result.data.businesses[position]);
})
.catch(err => console.log(err));
});
PlanActions.js:
import axios from 'axios';
import { GET_FOOD_PLANS, PLAN_LOADING, GET_ERRORS, GET_ACTIVITY_PLANS } from
'./types';
// Get Plans
export const getFoodPlans = () => dispatch => {
dispatch(setPlanLoading());
axios
.get('/api/data/food')
.then(res =>
dispatch({
type: GET_FOOD_PLANS,
payload: res.data
})
)
.catch(err =>
dispatch({
type: GET_FOOD_PLANS,
payload: err
})
);
};
planReducer.js:
import { GET_FOOD_PLANS, GET_ACTIVITY_PLANS, PLAN_LOADING } from
'../actions/types';
const initalState = {
food: {},
activities: {},
triggered: false,
loading: false
};
export default function(state = initalState, action) {
switch (action.type) {
case PLAN_LOADING:
return {
...state,
loading: true
};
case GET_FOOD_PLANS:
return {
...state,
food: action.payload,
loading: false
};
case GET_ACTIVITY_PLANS:
return {
...state,
activities: action.payload,
loading: false
};
default:
return state;
}
}
PlanTomorrow.js:
import React from 'react';
import PropTypes from 'prop-types';
import { getFoodPlans } from '../../actions/planActions';
import { connect } from 'react-redux';
import axios from 'axios';
import ResultBox from '../Resultbox/ResultBox';
class PlanTomorrow extends React.Component {
constructor(props) {
super(props);
this.state = {
load: false,
activity1: {},
};
}
componentWillMount() {
this.props.getFoodPlans();
axios.get('/api/data/activity').then(res => this.setState({ activity1:
res.data }));
}
render() {
return (
<div className="tomorrowform">
<h2>Tomorrows Plan:</h2>
<ul className="tomorrowform-data">
<li id="item1">
<ResultBox
activity={this.props.plan.food.name}
phone={this.props.plan.food.display_phone}
rating={this.props.plan.food.rating}
/>
</li>
<li id="item2">
<ResultBox
activity={this.state.activity1.name}
phone={this.state.activity1.display_phone}
rating={this.state.activity1.rating}
/>
</li>
</ul>
</div>
);
}
}
PlanTomorrow.propTypes = {
auth: PropTypes.object.isRequired,
plan: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth,
plan: state.plan
});
export default connect(
mapStateToProps,
{ getFoodPlans }
)(PlanTomorrow);
Upvotes: 1
Views: 759
Reputation: 1991
Two points:
this.props.getFoodPlans()
as you pass it to your component via connect.const isFoodExists = !this.props.plan.food || !this.props.plan.food.length;
if (this.props.loading || !isFoodExists) {
return null;
}
Here you should return the data for food as an array. And pass it as an array to your components.
Upvotes: 2