const CounterContext = createContext();
export function CounterProvider(props) {
const [count, setCount] = createSignal(0),
store = [
count
];
return (
<CounterContext.Provider value={store}>
{props.children}
</CounterContext.Provider>
);
}
export function useCounter() { return useContext(CounterContext); }
I want to use this useCounter
outside of the provider, after an external event like a setTimeout
or an incoming Websocket message.
setTimeout(() => {
const [count] = useCounter();
createEffect(on(count, () => {
console.log(count)
}))
})
This seems like a bad idea, but I have this in my application code, and I don't know how to restructure my code to avoid this.
CodePudding user response:
Generally I would look at getting the useContext call under the provider if possible or under a effect under the main rendering that is guarded. Yes you could use more advanced APIs like runWithOwner, but it probably will lead to other hiccups later if things are structured in a way you wouldn't be able to do that.
Normally the fix involves creating a signal that wires up the dynamic behavior you want synchronously, and then triggers it by setting the signal from the timeout.
CodePudding user response:
You can run asynchronous code with runWithOwner
to have access to the component's context.
// get component's owner
const owner = getOwner();
setTimeout(() => {
// timeout happens after the owner has been assigned to null
// in runWithOwner you have access to that owner's context
runWithOwner(owner, () => {
console.log(useContext(CounterContext));
});
});
Wrapping it with runWithOwner
also makes the computations created within dispose alongside the component - if you create a computation outside a root, it will never be disposed.
Playground link: https://playground.solidjs.com/?hash=1366672288&version=1.3.16