Reputation: 9875
Background
Since I started using redux thunk I have noticed a consistent problem with returning undefined or an object when I expect an array of objects. I am trying to understand how this works better so when I return the data to render it does not crash my application.
Problem
Currently I am making a fetch call within a action using redux thunk, I can see the data exist because I console.log
it out in the component where I plan on using it. As the page renders I can see it outputs an empty array twice then a third one with 100 objects inside the array.
The problem I face is when I try to call map or any of the array helper methods from Javascript it throws an error saying that
this.props.estimates.map is not a function
This is the normal error you see when you are not passing the correct data set to the helper method map
.
Example
Action
export function fetchEstimates() {
const URL = 'http://localhost:3001/estimates';
return dispatch => {
dispatch(estimatesRequest());
const getEstimates = fetch(URL, { method: 'GET' }).then(response => Promise.all([response, response.json()]));
return getEstimates.then(([response, json]) => {
if (response.status === 200) {
dispatch(estimatesSuccess(json));
} else {
dispatch(estimatesError());
}
});
};
}
export function estimatesSuccess(estimates) {
return {
type: 'ESTIMATES_SUCCESS',
estimates
};
}
Reducer
export default (state = [], action) => {
switch (action.type) {
case ESTIMATES_REQUEST:
return action;
case ESTIMATES_SUCCESS:
return action.estimates;
case ESTIMATES_ERROR:
return action;
default:
return initialState.estimates;
}
};
Component
render() {
console.log(typeof this.props.estimates);
return (
<Container>
<h1>Estimates</h1>
<Row>
<Col lg={12}>
{this.props.estimates.map((e, i) => (
<ul>
<li key={e.estimate_id}>{e.project_name}</li>
</ul>
))}
</Col>
</Row>
</Container>
);
Explanation
The console.log
in the components render method returns objet. But this is what the data looks like in the browser,
Please take note that the screenshot is from running the app one time. The output on one page refresh comes in this order,
I am wondering if the data is being removed at the end and that is the reason I am getting the error when I try and map the object to the render method.
Question
When this appears to be an array of objects, why am I showing it is an object when I call typeof
? How do I deal with this so I can map the values to the view as I am trying above? I am making the assumption this should be a different type so that it will map the values as expected instead of throwing an error or returning nothing.
Or is this a problem with the timing in which the data is returned from the fetch call?
Upvotes: 0
Views: 206
Reputation: 15292
In reducers,you are not initialised the estimates
.
some corrections :
state
should be {}
instead of []
;action
directly,please return state with merging of action payload data.Otherwise your component will missed some other values from returned state.Reducers :
export default (state = { estimates : []}, action) => {
switch (action.type) {
case ESTIMATES_REQUEST:
return Object.assign{{},...state,...action};
case ESTIMATES_SUCCESS:
return Object.assign{{},...state,...action.estimates};
case ESTIMATES_ERROR:
return action;
default:
return state;
}
};
Upvotes: 1