Context.Provider breaks reactivity
Need help with a simple Context Provider issue.
Here's a little sample of the code:
ESLint throws "The reactive variable 'contextValue' should be used within JSX, a tracked scope (like createEffect), or inside an event handler function, or else changes will be ignored."
And that's what happens. The ChildComponents which consume the context do not get updated.
What do I need to do to makes this work. Thanks a bunch ahead already.
14 Replies
Please use triple backticks to enclose your code so it is more easily readable 🙏
What do I need to do to makes this work.You simply pass
contextValue
directly, don't call it. Calling it means you pass the value, not the signal reference
Then, when you use the context, you need to call it to get the latest value
It's a little unfortunate that context appears to behave differently from most components in solid
With other components, you can rely on the compiler wrapping your props so that prop access is reactive, but because of the way context works, that doesn't help here
(Also, don't confuse context here with context in react, context in react is a state mechanism - it rerenders when context changes. In solid it just passes values down to components when they first render)
Hope that helpsIt still doesn't work. In the component which consumes the context with useContext...
When passing the value into the provider, you need to pass the signal (
contextValue
), not the value (contextValue()
)
What I wrote here
Then, when you use the context, you need to call it to get the latest valuerefers to the place you get the context (as in, from a
useContext()
call)
So
(Also, you're passing children to the div
twice, you could remove the {props.children}
and it will be passed through { ...props }
, if I remember correctly)
(that said, I'm a little surprised the linter knows you're passing into a provider, even though it's wrapped. Maybe it guesses based on the component + prop names?)I have adjusted to code in the parent to this
and on the child I'm doing this:
Try
state().open
Like hereYeah, that works :-). Typescript has thrown me off with "this expression is not callable"!?:
Yeah, you'll need to adjust the type you're using for the context
It's probably the reason for the type error on
value={}
here as well
Whatever type you're currently using for AccordionContextType
, you should wrap it with the Accessor<>
type from solid-js
And if you have a default value from the context, you'll need to wrap that value in a function as well, so the types are consistentYup. That was it. Thanks a bunch. Now it clicking. I didn't find that in the docs. Is there something you can recommend to check out when working with typescript and solid?
I just found this and that threw me off: https://docs.solidjs.com/guides/foundations/typescript-for-solid#context
Do you mind elaborating what there threw you off?
Shouldn’t there be the Accessor wrapped around the Data type just like you have mentioned above?
Like … createContext<Accessor<Data>>(()=>({count:0,name:””}))
Only if you're actually passing an accessor
You don't need to, if you're fine with the value being static
I need to check the context page, if it's clear enough about reactivity and context