Last week, I read React’s Learn React - Passing Data Deeply with Context documentation introducing the utility of Context. However, while reviewing it yesterday, I realized that I wasn’t clear on one thing.
My main question was that in some parts of the doc, they created context and set an initial value (e.g. const ThemeContext = React.createContext('light')
), whereas for other cases they didn’t (e.g. const ThemeContext = React.createContext()
or even set it to null const ThemeContext = React.createContext()
).
I didn’t quite understand the reason behind it, as well as how can you change the value of the context down the line?
Upon a bit of digging, I found React’s Reference - useContext to be incredibly helpful in ironing out the details.
Why is it meaningful to set an initial value of a context via createContext, if doing so is optional?
- It is truly optional if you are wrapping your component with a
<Context.Provider value={theme}/>
, since your component will be searching upwards the UI tree to get this value from the Context. - However, if a component is NOT wrapped by a Context.Provider, it will look at the initial value of the Context - therefore, setting an initial value of context is useful in preventing unexpected behavior or errors.
- Therefore, for me personally, I would probably set an initial value of a context, just IN CASE. My code sometimes has a mind of its own so I’d like to prevent as many errors as possible. :-)
Can you change the context value, and if so, how?
Yes, you can change the context!
If you want to update the value of the context, you can do so by combining it with a state, and then passing the value of that state to <Context.Provider value={}>.
// MyPage.jsx
import { ThemeContext } from './ThemeContext.jsx';
function Website() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={theme}>
<Form />
<Button onClick={() => {
setTheme(prevTheme => prevTheme === 'light? : 'dark' : 'light' );
}}>
{ theme === 'light' ? 'Switch to dark mode' : 'Switch to light mode' }
</Button>
</ThemeContext.Provider>
);
}
You can also pass down state variables as well as their setter/modifiers through a Context.Provider as a value.
<CurrentUserContext.Provider
value={{
currentUser,
setCurrentUser
}}
>
This code’s credit goes to the React.dev docs. :-)
- This way the children components down the UI tree can access the user information without receiving it as a prop.
Problem: getting undefined
from the context although initial value is different.
- Potential problem: Having a provider without passing a value down (e.g.
<ThemeContext.Provider></ThemeContext.Provider>
- If you omit the value, you are basically saying
value = undefined
- When this happens, React is very kind enough to send you a warning in the console :-)