Context API
Veles allows you to create Context, add it to your components and use it in children without passing anything directly; it also helps to encapsulate application-specific data. Keep in mind that Context is completely immutable and won’t trigger any re-renders on its own. The only way to get reactivity from the Context is to store a state there, and to subscribe to that state in individual components.
Here is a full example on how to use Context:
import { createContext } from "veles";
const exampleContext = createContext();
function App() {
exampleContext.addContext(5);
return (
<div>
<h1>Application</h1>
<NestedComponent />
</div>
);
}
function NestedComponent() {
const value = exampleContext.readContext();
// the value will be 5
return <div>{`Context value is ${value}`}</div>;
}
As of right now, there is no
defaultValue
for the Context
As you can see, we created a new Context, then added it inside the <App>
component, and then read it in the child component.
Reference
createContext()
Receives no parameters, returns a Context object with the following structure:
context.addContext(value)
Has to be executed inside a component initialization (it won’t work properly if you execute it in a lifecycle hook or in some event handler). Adds a value to the Context which will be available to all children, including the ones executed conditionally.
context.readContext()
Read currently saved Context value. If there were several Contexts added of the same object, the latest one will be used.
context.Provider
This is a component which adds Context to all the children. It works almost identical to context.addContext()
with a major caveat: children cannot be conditional. Because of that, I recommend to go with the context.addContext()
approach, but you can use this one as well. Here is an example of how to use it:
import { createContext } from "veles";
const exampleContext = createContext();
function App() {
return (
<exampleContext.Provider value={5}>
<div>
<h1>Application</h1>
<NestedComponent />
</div>
</exampleContext.Provider>
);
}
function NestedComponent() {
const value = exampleContext.readContext();
// the value will be 5
return <div>{`Context value is ${value}`}</div>;
}
Since the children are not conditional, it will work as expected. Here is an example when it won’t work as you expect:
import { createContext, createState } from "veles";
const exampleContext = createContext();
function App() {
const showState = createState(false);
return (
<exampleContext.Provider value={5}>
<div>
<h1>Application</h1>
<NestedComponent />
<button
onClick={() => showState.setValue((currentValue) => !currentValue)}
>
Toggle conditional component
</button>
{showState.useValue((shouldShow) =>
shouldShow ? <ConditionalComponent /> : null
)}
</div>
</exampleContext.Provider>
);
}
function NestedComponent() {
const value = exampleContext.readContext();
// the value will be 5
return <div>{`Context value is ${value}`}</div>;
}
function ConditionalComponent() {
const value = exampleContext.readContext();
// the value will be undefined
return <div>{`Context value in conditional component is ${value}`}</div>;
}
The component which is rendered at all times (<NestedComponent />
) will have the correct Context value, but the conditional one will not. Once you are inside a component, you can use state functions as usual, it is only about the direct children of context.Provider
.