Context API vs. Redux in a React Application
Cristina Radulescu
Posted on April 24, 2020
In this article I want to make a comparison between state in Redux and state in the Context API.
Redux
The state is maintained in a store which is connected to reducers, actions and middleware. In this example I will use saga middleware for fetching the information from the server and dispatching redux actions. The store information is then sent to the components using a Provider.
Store
export const sagaMiddleware = createSagaMiddleware();
const store = createStore(eventReducer);
sagaMiddleware.run(rootSaga);
export const EventsConnector = (props) => (
<Provider store={store}>
<AllEvents {...props}/>
</Provider>
);
Reducer
export const initialState = {
state: null,
events: [],
};
export const eventReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_EVENTS:
return {...state, state: "LOADING"};
case FINISH_FETCHING_EVENTS:
return {...state, events: action.data, state: "LOADED"};
}
return state;
};
Actions
The actions startFetchingEvents
and finishFetchingEvents
will be dispatched to update the state in Redux.
export const FETCH_EVENTS = "FETCH_EVENTS";
export const FINISH_FETCHING_EVENTS = "FINISH_FETCHING_EVENTS";
const createAction = (type, data) => ({ type, data });
export const startFetchingEvents = () => createAction(FETCH_EVENTS);
export const finishFetchingEvents = (events) => createAction(FINISH_FETCHING_EVENTS, events);
Setting the state
For setting the state an action startFetchingEvents
is dispatched which triggers the the saga which after fetching the events from the server will dispatch finishFetchingEvents
which will set the events
in the Redux state.
export function* fetchAllEventsEffect(action): * {
try {
const response = yield call(fetchEvents);
yield put(finishFetchingEvents(response.data));
} catch (e) {
console.error("Could not load events", e);
yield put(setError(e));
}
}
export default function* fetchAllEvents(): * {
yield takeLatest(FETCH_EVENTS, fetchAllEventsEffect);
}
export function fetchEvents() {
return axios.get('http://localhost:8080/allevents');
}
Context
The state is maintained in the Context and being handed over to the component using a Provider. When the getEvents
method is called, the state on the Context will be updated with the response from the server.
State
const EventContext = createContext();
const EventState = props => {
const initialState = {
events: [],
loading: false
};
const [state, dispatch] = useReducer(EventReducer, initialState);
const getEvents = async (name) => {
setLoading();
const result = await axios.get('http://localhost:8080/allevents');
const events = result.data;
dispatch({
type: GET_EVENTS,
payload: name ? events.filter(item => (item.name.toLowerCase()).includes(name)) : events
})
};
const setLoading = () => dispatch({type: SET_LOADING});
return (
<EventContext.Provider
value={{
events: state.events,
loading: state.loading,
getEvents,
}}>
{props.children}
</EventContext.Provider>
)
};
Reducer
export const GET_EVENTS = 'GET_EVENTS';
export const SET_LOADING = 'SET_LOADING';
export default (state, action) => {
switch (action.type) {
case GET_EVENTS:
return {
...state,
events: action.payload,
loading: false
};
case SET_LOADING:
return {
...state,
loading: true
};
default:
return state
}
}
Getting the state from Redux using containers
export const mapStateToProps = (state) => ({
events: state.eventDetails.events,
});
Getting the state from Context using hooks
const {events, loading, getEvents} = useContext(EventContext);
useEffect(() => { getEvents();}, []);
My opinion is that for new projects where you need to maintain the state, Context API is a better choice as it makes things a bit simpler than Redux. However, in projects where you are already using Redux, a migration to Context might not really be needed, as in the end both do implementation do the same thing, maintaining state.
You can clone the sample project from here.
In order to start the project you can follow the steps in the Readme. For the calls to server we will be using the mockserver.
Let me know in the comments section below if you already use the Context API and if you find it better than Redux and why.
Posted on April 24, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.