DEV Community

Cover image for Redux vs Context
sv0012
sv0012

Posted on

Redux vs Context

The usual way to share data between two components in react is through passing the data as props from parent to children.

Let us consider a counter parent component with three child components.

The child components would be :

  • The updating counter

  • Increasing button(to increase the counter value)

  • Decreasing button(to decrease the counter value)

Lets first consider the Redux approach.

Redux

Redux is all about dispatching actions which then change a central store causing the store to update the values.

The redux state management needs the following:

  • actions

  • reducers

  • store

Actions : Actions are the only source of information for the store as per the redux official documentation.It carries payload of information from your application to store.Actions are plain javascript object that must have a type attribute to indicate the type of action performed.

//actions
export const increment = () => {
return {
  type : 'INCREMENT_COUNT'
}
}

export const decrement = () => {
return {
  type:'DECREMENT_COUNT'
}
}

Enter fullscreen mode Exit fullscreen mode

Reducers : Actions only tell what to do,but they don't tell how to do,so reducers are the pure functions that take the current state and action and return the new state and tell the store how to do it.

The reducer uses a switch case that determine the action type,update the state and return the new state.

//reducers
var initState = {
  counter : 0
}

const counter = (state=initState,action) => {
switch(action.type) {
case 'INCREMENT_COUNT':
   return {
          ...state,
          counter:state.counter+1
          }

case 'DECREMENT_COUNT':
    return {
           ...state,
           counter:state.counter-1
           }
default : 
         return state
}
}

export default counter
Enter fullscreen mode Exit fullscreen mode

Store : The store is an immutable object tree in Redux.A store is a state container which holds the application's state.Redux can have only a single store in your application.

//store

import { createStore } from 'redux';
import rootReducer from '../reducers/index';

export const store = createStore(rootReducer);

Enter fullscreen mode Exit fullscreen mode

Now we need to make the store accessible to app hence we will wrap the counter app inside the component.

//main app import the necessary
export const ReduxMethod = () => {
return (
       <Provider store={store}>
         <Counter />
       </Provider>
);
}
Enter fullscreen mode Exit fullscreen mode

To access the state and dispatch actions we can use the useSelector and useDispatch hooks.

Now lets see the context approach.

Context

Context can be provided at some point in the app,it can be the root app component or another component and all the child component of the provided component will have access to that context.It provides a way to pass data across the component tree without having to pass props down at every level.

The context approach is much simpler when compared to the redux approach.The value in a context can be updated using a useState hook but since we have already seen the reducer functions let us use the same to update the state.




const countReducer = (state=initState,action) => {
switch(action.type) {
case 'INCREMENT_COUNT':
   return {
          ...state,
          counter:state.counter+1
          }

case 'DECREMENT_COUNT':
    return {
           ...state,
           counter:state.counter-1
           }
default : 
         return state
}
}

export default countReducer 

Enter fullscreen mode Exit fullscreen mode

For Context functionality we need to :

  • create the context

  • provide the context

  • consume the context

Creating the context :

  • A context is created using the createContext() and pass the initial state as arguments.Context can also be defined with passing any arguments.

  • define a function to pass the data through the provider

  • In the provider functions,use useReducer and pass the initial state and the reducer which will be passed as values in the provider.

//countState

const initState = {
        counter:0
}

export const CounterContext = createContext(initState);

export const CounterProvider = ({ children }) => {

const [state,dispatch]=useReducer(countReducer,initState);

return (
       <CounterContext.Provider value={{ state,dispacth }}>
         {children}
       </CounterContext.Provider>
);

}

Enter fullscreen mode Exit fullscreen mode

Providing the context : Provide the context to the counter app so that its child components have access to it.


export const ContextMethod = () => {
           return (
                <CounterProvider>
                  <Counter />
                </CounterProvider

)
} 

Enter fullscreen mode Exit fullscreen mode

Consuming the context: We use the useContext to use the values or set the values stored in the context.

Here to use the values the state and dispatch will be used,but whenever we use it we need to use the useContext and destructure it in the component.


const { state } = useContext(CounterContext);

//The state value represents the counter value

const {dispatch} = useContext(CounterContext);

//This will be used to update the state.

Enter fullscreen mode Exit fullscreen mode

Note:If we had used the useState instead of the reducer,the setState would be replacing the dispatch.

Now that we have understood the setup of both let us see when to use which.

Context:

  • In context when we update a particular value the same context used in other components for a different value of the context also re-renders again because context makes every component in the provider to re-render whenever data is changed.

  • Context is a built-in package of react which means we can use it without increasing the size of our project.

  • It has a simpler setup to get started with working on it.

  • Context is great to be used in static or rarely refreshed data.

Redux:

  • It is more commonly used and hence a lot of problems have been resolved.

  • Redux is great for often updating data as we can prevent unnecessary re-renders of the components.

  • Redux is easily integrated with redux via package.

  • Server side rendering is possible with redux.

Conclusion

In the case of small applications where data isn't changed often Context seems to be a better choice but when application is big and complex and the application state changes often Redux seems to be the winner.

Top comments (0)