I would like to know where I should fetch my data in the react life cycle.
I tried to put my data in the componentDidMount()
and componenWillMount()
but without succes...
componentWillMount(){
// this fetch the data from back-end set a store state with the payload
this.props.fetchUser();
this.setState({userData:this.props.auth});
}
//fetchMethod
export const fetchUser = () => async dispatch =>{//using redux-thunk
const res= await axios.get('/api/current_user')
dispatch({type:FETCH_USER, payload:res.data});
};
in my render function I tried to use fetched userData by calling this.state.userData
. but it's undefined. I also tried to get it by calling the correct store state, also without succcess. The thing I don't get is, according to my localstorage that store state is defined. Hope someone can tell me what I have done wrong.thanks!
You can do the fetch in the componentWillMount or the componentDidMount lifecycle methods (with the caveat being that when you have a server rendered application you will get issues of syncing your server rendered html and your rehydrated html if you make the request in the componentWillMount.)
The reason why your this.state.userData is undefined is because the call for your data is asynchronous in nature. I recommend adding functionality to your component to check if the api call is being made (isLoading
perhaps?), and if it is completed (isLoaded
perhaps?).
In terms of implementation, it would go something like this, assuming you use the connect
react-redux
higher order component:
class YourComponent extends React.Component {
componentDidMount() {
this.props.fetchUser();
}
render() {
const { isLoading, isLoaded, data } = this.props;
if (isLoading) return <Loader />; // Or whatever you want to return when it is loading
if (!isLoaded || !data) return null; // If it is not loading and its not loaded, then return nothing.
return (
<div>
<h1>{data.name}</h1>
<h2>{data.id}</h2>
</div>
)
}
}
const mapStateToProps = state => ({
isLoading: state.user.isLoading,
isLoaded: state.user.isLoaded,
userData: state.user.data
});
export default connect(mapStateToProps, { fetchUser })(YourComponent);
In your action dispatcher/middleware you will need to account for the start of the asynchronous call. Assuming that is accounted for with something like redux thunk...
const initialState = {
isLoaded: false,
isLoading: false,
data: {},
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_USER:
return {
...state,
isLoading: true,
}
case FETCH_USER_SUCCESS:
return {
isLoading: false,
isLoaded: true,
data: action.payload
};
default:
return state;
}
};
export default reducer;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With