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:
- Create a context object by using React.createContext()
- 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.
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
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
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
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.
Top comments (14)
For me, I had to add an empty
_value
like:Good working
It doesn't work for me, i don't have a getCopy, what this function does? could you please help me or get it touch with me!
Hey! Thank you for your message and sorry for the inconvenience caused.
Basically, getCopy() method could be anything whose result you want to set globally. In my case, it is a simple method which gets content based on the logged in user type.
For eg:
You can use localstorage for this:
Thank you for the alternative, however what if the user has disabled his localStorage? ;)
I did not know you can disable it
How will you change this when the objects to set and get are much more complex?
I have something like :
export interface IDocumentInfo {
file: IFilePickerResult;
pages?: number;
instructions?: string;
existsOnsite?: boolean;
}
export interface IRequestInfo {
projectNumber: string;
documents: IDocumentInfo[];
}
and I want a global context for an IRequestInfo object.
Thank you
Nice post
Thanks a lot Ben :). Being my first technical post, I am glad you liked it :)
medium.com/@masterrajpatel/useglob...
tried to explain the same , see if it can help others
Thanks a lot! I started lo learn Typescript recently and you save me a lot of time. I would buy you a beer if I could. Cheers!
haha, that is really sweet Manuel! Glad, I was able to help :)
Men o'zimga shuncha oldim.
Some comments have been hidden by the post's author - find out more