Context
Context allows you to pass a value to a child deep down the tree without having to pass it through every component in-between via props. A very popular use case for this is theming. In a nutshell context can be thought of a way to do pub-sub-style updates in Preact.
There are two different ways to use context: Via the newer createContext
API and the legacy context API. The difference between the two is that the legacy one can't update a child when a component inbetween aborts rendering via shouldComponentUpdate
. That's why we highly recommend to always use createContext
.
createContext
First we need to create a context object we can pass around. This is done via the createContext(initialValue)
function. It returns a Provider
component that is used to set the context value and a Consumer
one which retrieves the value from the context.
The initialValue
argument is only used when a context does not have a matching Provider
above it in the tree. This may be helpful for testing components in isolation, as it avoids the need for creating a wrapping Provider
.
const Theme = createContext('light');
function ThemedButton(props) {
return (
<Theme.Consumer>
{theme => {
return <button {...props} class={'btn ' + theme}>Themed Button</button>;
}}
</Theme.Consumer>
);
}
function App() {
return (
<Theme.Provider value="dark">
<SomeComponent>
<ThemedButton />
</SomeComponent>
</Theme.Provider>
);
}
Run in REPL
An easier way to use context is via the useContext hook.
Legacy Context API
We include the legacy API mainly for backwards-compatibility reasons. It has been superseded by the createContext
API. The legacy API has known issues like blocking updates if there are components in-between that return false
in shouldComponentUpdate
. If you nonetheless need to use it, keep reading.
To pass down a custom variable through the context, a component needs to have the getChildContext
method. There you return the new values you want to store in the context. The context can be accessed via the second argument in function components or this.context
in a class-based component.
function ThemedButton(props, context) {
return (
<button {...props} class={'btn ' + context.theme}>
Themed Button
</button>
);
}
class App extends Component {
getChildContext() {
return {
theme: 'light'
}
}
render() {
return (
<div>
<SomeOtherComponent>
<ThemedButton />
</SomeOtherComponent>
</div>
);
}
}
Run in REPL