Published
- 4 min read
How to use context api in react.js
Overview
If you want to create an application you are required to use global state management. You will probably install redux and you have to write a lot of boilerplate code and overwhelming stuff for basic store implementation which is still fine but it will also increase the build size of your application because of installing external libraries like **redux, react-redux, @ redux/toolkit **, etc. React context API is already providing a great way to manage your state across all the components. In this tutorial, I’m using a very simple way to implement useContext API and useReducer hook to create a simple global state like a redux reducer.
To start with:
What is Context API?
Context API is used to share data between components without props drilling which means passing data to the children and then further down its children. which becomes chaotic and makes the code more complex, Its built-in API in React which is good for the performance of the application.
What is useReducer Hook?
To understand the useReducer hook. First, we need to understand what is the reducer.
A reducer is a pure function that takes state and action as a parameter and returns a newly modified state according to the action passed to it.
Now,
the useReducer hook is used to define the reducers of peace of a state in your application. It also accepts two parameters, initial state, and reducer function within the body of useState hook and returns state and dispatch properties. Here is the example of using useReducer hook
const initialState = []
const reducer = (state, action) => {
switch (action.type) {
case 'ADD':
return [...state, action.payload]
case 'COMPLETE':
return state.map((todo) => {
if (todo.id === action.id) {
return { ...todo, isComplete: !todo.isComplete }
} else {
return todo
}
})
default:
return state
}
}
const [state, dispatch] = useReducer(initialState, reducer)
Step-by-Step Implementation
Let’s create a new react project by running npx create-react-app react-context
or yarn create vite
and select React Project. I’m creating a very simple todo context in this example
Now, we have a blank project. create a new file under src/context/todoContext.jsx. I’m creating a React component with context implementation which will be used as the parent component of the application. I’m creating two contexts one for getting the state values and the other for setting the values i.e. reducer. Also add useReducer code which I’ve explained above
import React, { createContext, useReducer } from 'react'
export const TodoContext = createContext(null)
export const TodoDispatchContext = createContext(null)
const TodoProvider = ({ children }) => {
const [state, dispatch] = useReducer(initialState, reducer)
return (
<TodoContext.Provider value={state}>
<TodoDispatchContext.Provider value={dispatch}>{children}</TodoDispatchContext.Provider>
</TodoContext.Provider>
)
}
export default TodoProvider
Now!
We have created the todo context. We import this component in our main entry file entry and wrap around the whole application
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import TodoProvider from './context/todoProvider'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<TodoProvider>
<Todo />
</TodoProvider>
</React.StrictMode>
)
Alright!
We have successfully created and wrapped our todo context in our application. Now we can get state and dispatch from anywhere inside the application. At this stage, we are using another hook called useContex since we are using the contexts that we created above. Let’s see how it works
src/components/todo.jsx
import React, { useContext } from 'react'
import { TodoContext, TodoDispatchContext } from '../context/todoContext'
const Todos = () => {
const todos = useContext(TodoContext)
const dispatch = useContext(TodoDispatchContext)
return (
<div>
{todos.map((todo) => (
<div>
<h2>{todo.text}</h2>
</div>
))}
</div>
)
}
export default Todos
Finally, Let’s write some UI code to utilize the workflow of the state management.
import React, { useContext } from 'react'
import { TodoContext, TodoDispatchContext } from '../context/todoContext'
const Todos = () => {
const todos = useContext(TodoContext)
const dispatch = useContext(TodoDispatchContext)
return (
<div>
{todos.map((todo) => (
<div className='todo-body'>
<span className={todo.isCompleted ? 'todo-completed' : 'to-uncompleted'}>
{todo.text}
</span>
<input
type={'checkbox'}
value={todo.isCompleted}
onChange={(e) => dispatch({ type: 'COMPLETE', id: todo.id })}
/>
</div>
))}
<div className='add-todo'>
<input type={'text'} value={todoText} onChange={(e) => setTodoText(e.target.value)} />
<button
className='add-btn'
onClick={() => {
dispatch({
type: 'ADD',
payload: {
text: todoText,
id: Date.now() //This returns timestamp as a unique number and I'm using this as id
}
})
}}
>
Add TODO
</button>
</div>
</div>
)
}
export default Todos
Conclusion
You have implemented context api in your react.js application. It’s the simplest way to manage the state of the application globally without using libraries like redux. I use context api for small applications because its very simple to use. Global state management tools like redux makes application a little bit complex for small apps.