🦉 Context 🦉

Content

Overview

The Context object provides a way to share data between an arbitrary number of components. Usually, data is passed from a parent to its children component, but when we have to deal with some mostly global information, this can be annoying, since each component will need to pass the information to each children, even though some or most of them will not use the information.

With a Context object, each component can subscribe (with the useContext hook) to its state, and will be updated whenever the context state is updated.

Example

Assume that we have an application with various components which needs to render differently depending on the size of the device. Here is how we could proceed to make sure that the information is properly shared. First, let us create a context, and add it to the environment:

const deviceContext = new Context({ isMobile: true }); App.env.deviceContext = deviceContext;

If we want to make it completely responsive, we need to update its value whenever the size of the screen is updated:

const isMobile = () => window.innerWidth <= 768; window.addEventListener( "resize", owl.utils.debounce(() => { const state = deviceContext.state; if (state.isMobile !== isMobile()) { state.isMobile = !state.isMobile; } }, 15) );

Then, each component that want can subscribe and render differently depending on the fact that we are in a mobile or desktop mode.

class SomeComponent extends Component { static template = xml` <div> <t t-if=device.isMobile> some simplified user interface </t> <t t-else=""> a more advanced user interface </t> </div>`; device = useContext(this.env.deviceContext); }

Reference

Context

A Context object should be created with a state object:

const someContext = new Context({ some: "key" });

Its state is now available in the state key:

someContext.state.some = "other key";

This is the way some global code (such as the responsive code above) should read and update the context state. However, components should not ever read the context state directly from the context, they should instead use the useContext hook to properly register themselves to state changes.

Note that the Context hook is different from the React version. For example, there is no concept of provider/consumer. So, the Context feature does not by itself allow the use of a different context state depending on the component place in the component tree. However, this functionality can be obtained, if necessary, with the use of sub environment.

useContext

The useContext hook is the normal way for a component to register themselve to context state changes. The useContext method returns the context state:

device = useContext(this.env.deviceContext);

It is a simple observed state (with an owl Observer), which contains the shared information.