Struggling With Context API ? You Are Not Alone.
Tags: webdev, javascript, beginners, react
Published: 2022-07-04 13:03:29

State is an **essential** part of our React application, hence, the need to pass to different components. state/data is passed top-down (parent to child) via **props**. This is called **PROP DRILLING**.
![Prop drilling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylzg1p3zr6ompxsy0kyq.png)

This method becomes complex as the application grows and as many components require different props.
Things can get messy in a twinkle of an eye.


**Context** provides a way to share values like these between components without having to pass a prop through every level of the tree.
 
<u>In this guide, we would talk about **context API**, and its usage and build a mini-project ( a search application ) with it.
Let's dive in.</u>
 
Context is designed to share data that can be considered **global** for a tree of React components, such as the current authenticated user, theme, etc.

I am guessing your editor is already set up.
 
### Set up Context API

First, we have to create a file called **ResultContext.js** (feel free to name it whatever you want) and import the required hooks.

`import React , { useContext , useState , createContext } from "react"`

- Create Context
```jsx
const ResultContext = createContext()
```

- Create a **"Provider"** and add {children} as a prop
```jsx
export const ResultContextProvider = ( {children }) => {
//state for results
const [results , setResults ] = useState([]);
//state for search Term
const [searchTerm , setSearchTerm ] = useState('Elon Musk');

//create a function to fetch data

const getResults = async () => {
    const options = {
        method: 'GET',
        headers: {
            'X-API-Key': process.env.REACT_APP_API_KEY,
        }
    };
        
    const response = await fetch('https://google
search3.p.rapidapi.com/api/v1/search', options)

    const data = await response.json();
    //set results to the results gotten from data fetched
    setResults(data.results)
}
```

- Return Context.Provider inside the previously created Provider and set **value** to the props to be passed.

```jsx
return (
    <ResultContext.Provider value= { { getResults , results , searchTerm , setSearchTerm } } >
        {children}
    </ResultContext.Provider>
)
}
```

We are done with setting up our context file. **In summary:**

1. We created context using the **createContext()** hook.
2. We created  A **"provider"** and passed {children} as a prop and returns ResultContext.Provider. 
3. We fetched data and set the **results state** to the data fetched.
4. We returned a ResultContext.Provider and set value to the states we want to pass as props into other components. Whatever we pass into the value prop will be available throughout our app.

### Wrap the App component with the Provider 
```js
import React from 'react';
import App from './App';
import { ResultContextProvider } from
'./context/ResultContextProvider';
import { createRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = createRoot(container);

//wrap <App /> with Provider to make state available through app
root.render(
     <ResultContextProvider>
          <Router>
               <App />
          </Router>
     </ResultContextProvider>
);
```

### Consume the props
Now the state/Props are available throughout the App, we now need to consume them.

1. Import the required Hooks 
`import React, { useEffect, useContext } from 'react'`
The **useContext** hook is used to get the props from the context.

2. Import the context
`import { ResultContext } from '../context/ResultContext'`

3. Get the props from the context using **useContext**

```jsx
//component for search
import React, { useEffect, useState, useContext } from 'react';
import { ResultContext } from '../context/ResultContext';

const Search = () => {
  //get prop from context
  const { setSearchTerm } = useContext(ResultContext);
  const [text, setText] = useState('');

  //change the value of text throughout our app
  useEffect(() => {
    if (text) {
      setSearchTerm(text)
    }
  }, [text]);

  return (
    <div>
    <div>
      <input
        value={text}
        type="text"
        onChange={(e) => setText(e.target.value)}
      />  
        
    {text !== '' && (
      <button type="button" onClick={() => setText('')}>x</button>
    )}
    </div>
  )
}

export default Search;
```



```jsx
//component displaying result
import React, { useEffect, useContext } from 'react'
import { useResultContext } from '../context/ResultContext';


const News = () => {
  const { results, getResults, searchTerm } =  useContext(ResultContext);

  useEffect(() => {
    if (searchTerm !== '') {
      getResults();
  }
}, [searchTerm]);


return (
  <div>
  {results?.map(({ link, title, description }, index) => (
  <div key={index}>
    <a href={link} target="_blank" rel="noreferrer">
      <p>{link.length > 30 ? link.substring(0, 30) : link}</p>
      <p >{title}</p>
      <p>{description}</p>
    </a>
  </div>
  ))} 
  </div>
)
}
export default News
```


### Conclusion
_The main takeaways from this article include the following:_
The React Context API is designed for prop drilling

This example is fairly simple and I hope you’ve been able to understand how to handle State in React using the context API.