When managing state in a React application, two powerful tools are available: React Context and Redux. Both tools help in solving the problem of prop drilling—when data needs to be passed through multiple layers of components. While React Context is built into React for sharing data across the component tree, Redux is a more advanced state management library that allows for managing global application state more effectively.
React Context is a built-in API for passing data across the component tree without needing to pass props manually at each level. It allows data to be shared globally in your application.
React Context is especially useful when you need to pass data that is used by many components, like themes, language settings, or authenticated user data.
Let’s look at a simple example where we use React Context to manage and share a theme across multiple components.
import React, { createContext, useState } from 'react';
// Create a Context
export const ThemeContext = createContext();
// Create a Context Provider Component
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
{children}
);
};
createContext()
: Creates a new Context object. This will hold the value we want to share across components.ThemeProvider
: This component wraps other components and provides them with access to the theme and toggleTheme
function through the ThemeContext.Provider
.
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeProvider';
const Header = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
{theme === 'light' ? 'Light Theme' : 'Dark Theme'}
);
};
export default Header;
useContext()
: We use the useContext
hook to access the theme
and toggleTheme
provided by the ThemeProvider
. This eliminates the need to pass the theme
as a prop from the parent component to the child components.When this code is run, the Header
component will show either a “Light Theme” or “Dark Theme” header based on the current theme. The user can toggle the theme using the button, and the background color of the header will change accordingly.
Redux is a popular state management library designed to manage complex application state. Unlike React Context, which is best for simple state sharing, Redux is ideal for applications with a lot of data or complex interactions. It follows a predictable state container model, allowing your app’s state to be managed centrally and updated in a controlled, predictable manner.
Before using Redux, you need to install the redux
and react-redux
libraries.
npm install redux react-redux
1. Creating the Redux Store:
// store.js
import { createStore } from 'redux';
// Define the initial state
const initialState = {
count: 0,
};
// Create a reducer
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
default:
return state;
}
};
// Create the Redux store
const store = createStore(counterReducer);
export default store;
count
variable.counterReducer
function handles different actions to modify the count
value.INCREMENT
: Increases the count by 1.DECREMENT
: Decreases the count by 1.createStore
function creates the Redux store using the counterReducer
.
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';
ReactDOM.render(
,
document.getElementById('root')
);
Provider
component from react-redux
wraps the entire app, giving all components access to the Redux store.
// Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
const Counter = () => {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
Count: {count}
);
};
export default Counter;
count
) from the Redux store.dispatch
function is used to send actions (e.g., INCREMENT
and DECREMENT
) to the store, which updates the state.The component will display the current count and have two buttons to increment and decrement the count. Each time a button is clicked, the state is updated in the Redux store, and the new count is rendered.
Now that we’ve covered both React Context and Redux, let’s compare them in detail.
redux-thunk
or redux-saga
.Redux doesn’t handle async actions out of the box, but with middleware like redux-thunk
, you can manage async logic like API calls.
redux-thunk
:
npm install redux-thunk
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
const fetchData = () => {
return (dispatch) => {
dispatch({ type: 'FETCH_REQUEST' });
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => dispatch({ type: 'FETCH_SUCCESS', payload: data }))
.catch((error) => dispatch({ type: 'FETCH_FAILURE', error }));
};
};
const initialState = { data: [], loading: false, error: null };
const dataReducer = (state = initialState, action) => {
switch (action.type) {
case 'FETCH_REQUEST':
return { ...state, loading: true };
case 'FETCH_SUCCESS':
return { ...state, loading: false, data: action.payload };
case 'FETCH_FAILURE':
return { ...state, loading: false, error: action.error };
default:
return state;
}
};
const store = createStore(dataReducer, applyMiddleware(thunk));
FETCH_REQUEST
to indicate the start of a request, FETCH_SUCCESS
with the data if the request succeeds, and FETCH_FAILURE
with an error if it fails.Both React Context and Redux serve the purpose of state management in React applications, but they are suited to different use cases.React Context is a great option for simple or medium-scale applications where you need to pass data globally without prop drilling. It’s easy to set up, requires minimal boilerplate, and works well for things like themes or authentication data.Redux, on the other hand, is a more powerful tool designed for complex state management in large applications. It provides a centralized store, powerful middleware support, and advanced debugging tools, but comes with more complexity and boilerplate. Happy Coding!❤️