useContext() with Typescript
Tags: react, reacthooks, typescript, programming
Published: 2021-01-18 21:53:58

The below article will give you an overview with an example of how to use the `useContext()` hook and also update the globally set context value in child components.

**Prerequisites:** Basic familiarity with React and Typescript

Usually, in a React application, data is passed top-down (parent to child) via props. The reason third party state management libraries like Redux became so popular is due to the prop drilling problem of React.

Prop drilling consists of passing a prop to the nested child components, and as a result, children who do not need this prop, still end up getting it even though they might never use it.

useContext() hook makes it easy to pass data throughout your app without manually passing props down the tree. It allows to create a `global state` and the required child components can consume it.

useContext() can prove to be a `simple alternative` to other state management libraries if your data is not complicated and the application is small.

>This is what the process involves:
>1. Create a context object by using React.createContext()
>2. Provide the globally created context to your child >components using Provider

_Example using Typescript:_

In the below example, I want to set the value of content globally based on the user type passed which can be consumed by the nested child components. I will also update the value of content in one of the nested child component.

Let’s get started 🙌

- Initialise, the context at a top-level using a default value. Create a global context hook useGlobalContext()

I have created a GlobalContent type which has copy and a setCopy(). The reason for using setCopy() will be clarified later.

 ```javascript
import { createContext, useContext } from "react"
export type GlobalContent = {
  copy: string
  setCopy:(c: string) => void
}
export const MyGlobalContext = createContext<GlobalContent>({
copy: 'Hello World', // set a default value
setCopy: () => {},
})
export const useGlobalContext = () => useContext(MyGlobalContext)
```

- Wrap the context at the parent level to which the value of context would be accessible for its child components. I have wrapped it around the child components in App.tsx

In the below example, the `getCopy()` is getting the copy based on the logged in Admin user and making it available for the child components Home and About

```javascript
import { MyGlobalContext } from './MyGlobalContext'
import React, { useState } from 'react'
import { getCopy } from './Content'
import { Home } from './Home'
import { About } from './About'
function App() {
const [copy, setCopy] = useState<string>(getCopy('Admin'))
return 
  (
   <MyGlobalContext.Provider value= {{ copy, setCopy }}>
     <Home/> 
    <About/>
  </MyGlobalContext.Provider>
  )
}
export default App
```

- Utilise the globally set value of copy in your child component Home.tsx

```javascript
import { useGlobalContext } from './MyGlobalContext'
const Home = () => {
const { copy } = useGlobalContext()
return <div>{copy}</div>
}
export default Home
```

That is it!!!! Your useContext() hook is in use and you have successfully set the value of copy i.e. content globally 😄.

You must be wondering why do we still have an unused setCopy() 🤔

As I mentioned at the beginning of the article, if you ever want to update the value of copy in child components, you need to pass a function to update the copy. In our case, `setCopy()` will allow you to update the copy.

In the below example, I am setting a new value for copy on the click of a button and passing it to the nested child component MyProfile.tsx

```javascript
import { useGlobalContext } from './MyGlobalContext'
import { MyProfile } from './MyProfile'
const About = () => {
const { copy, setCopy } = useGlobalContext()
return(
   <>
    <button onClick={() => setCopy('This is a new copy')}>
      Click me!
    </button>
    <MyProfile newContent={copy} />
  </>
 )
}
export default About
```

That’s it. Believe it or not, with what you learned above (or parts of it, really), you can start using useContext() hook and create a global state for your application.