INTRODUCTION
Before the introduction of the Context API, using react for me was very tedious and cumbersome. Using react reminds me of the linked list data structure, one node points to another node for you to get that which you want. Managing an application state was tedious and tasking because we have to pass data most times from one component to another. This presents an issue when our application gets larger and this is what we call prop drilling or threading.
What is Prop drilling or threading?
Prop drilling is the process of passing data from one node or component of the application to another component. What makes prop drilling tasking is that sometimes we pass this data through components that do not necessarily need them. This sounds like redundancy to that particular component right?
Prerequisite
As a background knowledge for this article, you are expected to have a basic understanding of react and also know how hooks in react work.
What is Context API?
We’ve talked about the flow of react without context API and how tasking it is. What then is the context API?
In comparison to the prop drilling pattern that passes data from one component to another till it gets to the desired component, Context API brings to mind the tree data structure. The tree data structure has a central parent node, then every other node connects to it or that immediate parent. Similarly, the context API uses a central store which connects to our internal database or external database through an API and stores all data. Any component in need of the data can easily connect to the store for access.
Important hooks / concept to understand
useState hook
The useState hook is a react feature that helps you use state in a functional component. Just as a recap if you don’t know, in react we have two was of declaring components; functional and class components. useState usually takes in a state variable which changes and another variable setState which acts as a method that changes the state variable.
Syntax
const [state, setState] = useState(initialState)
useContext hook
The useContext hook helps you assign the data from the context store down to a particular state in our child component. It is one of the major hooks used in the Context API. It takes in the store data passed down as an argument.
Syntax
const [state, setState] = useContext(functionFromStore)
useEffect hook
The useEffect hook is used for performing a particular function after our document object model (DOM) has been rendered. We can do a variety of tasks in the useEffect hook, we can fetch data from our database whether it be fetching data or assigning values.
Syntax
useEffect(() => {
do something here
}, []);
Now that we’ve dealt with useState, useEffect and useContext hooks, let’s see how they fit together writing a simple program. We are going to be fetching data from the jsonplaceholder api and passing it to another component. We’ll be working with three major files. Our store, app, and show_post files in this order. For our store file, we’ll import our useState, useEffect, and createContext hook. The createContext performs as the name implies.
import React, {useState, useEffect, createContext} from 'react';
After our import, we then create our context and pass it to a variable, which we’ll also use to send our data to the other files.
export const PostContext = createContext();
Now, we can create our functional component, where we’ll declare our state, since we are fetching post from external database, we’ll use our useState hook to create a state which we hold our result, we’ll also use our useEffect hook where we’ll connect to the endpoint and get our data. After fetching the data, we’ll use our setPost to assign those data to our post state. Then call on our PostContext which we’ve created earlier to export that data for any other component needing it to hook on. The provider property chained to our PostContext is like our messenger which sends the information in this case, post to another component.
export const PostProvider = (props) => {
const [post, setPost] = useState([
]);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts`)
.then(response => response.json())
.then(data =>{ setPost(data)})
}, [])
return(
<PostContext.Provider value={[post, setPost]}>
{props.children}
</PostContext.Provider>
);
}
Proceeding to our App file, we’ll be importing our PostProvider function which we’ve just exported and also calling on any other component that we’ll be needing data from our store.
import React from 'react';
import {PostProvider} from './store';
import PostComponent from './Component/PostComponent'
We’ll just need to wrap any component that needs to connect to our store into a parent PostProvider anchor like this below. In our instance here, and will be connecting to our store
function App() {
return (
<PostProvider>
<div className="container">
<PostComponent/>
</div>
</PostProvider>
)
}
Let’s see our last file and how we can bring to use the fetched from the store file. Like before, we import our function PostContext and the necessary hooks. Then, we create our functional component, declare our state and assign the data fetched to the post state. In our return, we just need to iterate through our state using the map function which is one of javascript high order functions to get our data.
import React, {useEffect, useState, useContext} from 'react';
import {PostContext} from '../store';
const PostComponent = () => {
const [posts, setPost] = useContext(PostContext);
return(
<ul>
{
posts.map((post,i) => {
return (
<li key={i}><b>{post.title}</b> <br/> - {post.body}<br/>
</li>
)
})
}
</ul>
)
}
And that’s how we wrap this session.
NB: We have other state management like Redux, mobX which is used for complex state management. The Context API helps in resolving the problem with prop drilling. It also works well as a state management tool for very small applications.