ContextEdit this page
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
When to use context
When you have a large component tree that requires state to be shared, context can be used. Context can be employed to avoid prop drilling, which is the practice of passing props through intermediate elements without using them directly.
If you only want to avoid passing some props through a few levels levels, component composition is often a simpler solution than context.
Signals are often a simplest solution since they can be imported directly into the components that need them.
Context is designed to share data that can be considered "global", or information that is regularly accessed by many components in your application or component tree. It offers a way to access values more efficiently instead of passing props through intermediate elements or importing them directly into components.
Context is created using the
This function has a
Provider property that wraps the component tree you want to provide context to.
Providing context to children
To pass a value to the
Provider, you use the
value prop which can take in any value, including signals.
Once a value is passed to the
Provider, it is available to all components that are descendants of the
When passing a single value, it can be directly passed to the
However, if you need to access multiple values, they must be passed as an object literal, or using double curly braces (
Once the values are available to all the components in the context's component tree, they can be accessed using the
This utility takes in the context object and returns the value(s) passed to the
When you are passing multiple values into the
Provider, you can destructure the context object to access the values you need.
This provides a readable way to access the values you need without having to access the entire context object:
Customizing context utilities
When an application contains multiple context objects, it can be difficult to keep track of which context object is being used. To solve this issue, you can create a custom utilities to create a more readable way to access the context values.
For example, when wrapping a component tree, you may want to create a custom
Provider component that can be used to wrap the component tree.
This also provides you with the option of re-using the
Provider component in other parts of your application, if needed.
Now if you had to access the Provider in different areas of your application, you can simply import the
CounterProvider component and wrap the component tree:
Similarly, you can create a custom utility to access the context values.
Instead of importing
useContext and passing in the context object on each component that you're using it in, creating a customized utility can make it easier to access the values you need:
useCounter() utility in this example can now be imported into any component that needs to access the context values:
Updating context values
Signals offer a way to synchronize and manage data shared across your components using context.
You can pass a signal directly to the
value prop of the
Provider component, and any changes to the signal will be reflected in all components that consume the context.
This offers a way to manage state across your components without having to pass props through intermediate elements.
Debugging with context
createContext takes in an optional default value and it is possible it can return
undefined if not provided.
When working with TypeScript, this can introduce type issues that make it difficult to determine why your component is not rendering as expected.
To solve this issue, a default value can be specified when creating a context object, or errors can be handled manually through the use of a custom