context
is a just a fancy technique of passing props
without worring about hierarchy.
Decoupling the data flow is the only differential when comparing with normal props
. So changing the value of a context
comes with the some caveats.
When you need to change a shared state between parent and child you need to lift your state up and pass down a way of changing it. With context
is no different
Assume the following provider which pass down a theme
and a way of chage it
export const context = createContext()
const { Provider } = context
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState({ color: 'foo' })
const value = { theme, setTheme }
return (
<Provider value={value}>
{children}
</Provider>
)
}
You still need to pass down a handler to change the state. To change theme
from inside a Component
(which is descendent of ThemeProvider
) you can do like this
import { useContext } from 'react'
import {context} from './ThemeProvider'
const Component = () =>{
const {theme, setTheme} = useContext(context)
const handleChange = () => setTheme({color:'blue'})
return <button onClick={handleChange}>Change</button>
}
Usually (not necessarily) Providers
are declared in the top-level component App.js
//App.js
import { ThemeProvider } from './ThemeProvider'
const App = () =>{
<ThemeProvider>
<RestOffYourApp />
</ThemeProvider>
}