Reputation: 3365
I'm having a bit of trouble getting my application to work how I'd like it. I'm fairly new to React and Redux so bear with me.
Right now I can call this.props.fetchData('usernamehere')
to fetch some data about a user, when it's successful it updates this.props.profile
which I use to update the React component. The problem with this is handling errors.
I've tried to handle this by adding a FETCH_DATA_ERROR
reducer, but the problem I'm having is that when it 404's it still replaces this.props.profile
with an empty object instead of just updating this.props.error
. Ideally I want to keep the current profile until it successfully finds a new one, and then show the user what the error was with the username they entered by updating this.props.error
.
Right now I have the following action creator setup:
import axios from 'axios';
import { FETCH_DATA, FETCH_DATA_ERROR } from './types';
export const ROOT_URL = 'https://api.github.com/users'
export function fetchData(user) {
const request = axios.get(`${ROOT_URL}/${user}`)
.catch(function (error) {
return {
type: FETCH_DATA_ERROR,
payload: error
}
});
return {
type: FETCH_DATA,
payload: request
}
}
And reducer:
import { FETCH_DATA, FETCH_DATA_ERROR } from '../actions/types';
const INITIAL_STATE = { profile: null, error: null }
export default function(state = INITIAL_STATE, action) {
switch(action.type) {
case FETCH_DATA:
return { ...state, profile: action.payload.data };
case FETCH_DATA_ERROR:
return { ...state, error: action.payload };
default:
return state;
}
}
If anyone has any suggestions they would be greatly appreciated. I feel like I'm on the right path but can't seem to figure out where I'm going wrong.
Upvotes: 3
Views: 1507
Reputation: 2925
So far you have an action that signals the beginning of the request (FETCH_DATA
) and one that signals that the request failed (FETCH_DATA_ERROR
). Typically this is modelled with a third one, that signals that the request resulted in a positive response (maybe FETCH_DATA_SUCCESS
).
You would need to rewrite your action creator using something like https://github.com/gaearon/redux-thunk so that it first dispatches only FETCH_DATA
, and then in the then/catch-handlers of axios.get
you dispatch the success or failure actions:
import { FETCH_DATA, FETCH_DATA_SUCCESS, FETCH_DATA_ERROR } from '../actions/types';
// ASYNC ACTION CREATOR
export const fetchData = user => (dispatch) => {
dispatch({
type: FETCH_DATA
});
return axios.get(`${ROOT_URL}/${user}`)
.then(response => dispatch({
type: FETCH_DATA_SUCCESS,
payload: response
}))
.catch(error => dispatch({
type: FETCH_DATA_ERROR,
payload: error
}));
};
// REDUCER
const INITIAL_STATE = {
profile: null,
error: null
};
export default function(state = INITIAL_STATE, action) {
switch(action.type) {
// Start of request - discard old data and reset old errors.
case FETCH_DATA:
return {
// It's important to set all of these to properly model the request lifecycle
// and avoid race conditions etc.
profile: null,
error: null
};
// End of request - save profile and signal that there was no error.
case FETCH_DATA_SUCCESS:
return {
profile: action.payload.data,
error: null
};
// End of request - discard old profile and save error, to display it to the user for example.
case FETCH_DATA_ERROR:
return {
profile: null,
error: action.payload
};
default:
return state;
}
}
Upvotes: 1