Is there any secure alternative to createEffect?
About the following statement on createEffect documentation:
"Effects are meant primarily for side effects that read but don't write to the reactive system: it's best to avoid setting signals in effects, which without care can cause additional rendering or even infinite effect loops. Instead, prefer using createMemo to compute new values that depend on other reactive values, so the reactive system knows what depends on what, and can optimize accordingly."I get the point on the "best to avoid setting signals" inside a createEffect, but that's precisely what I need to do. Is there any other solid primitive to run my effect securely to avoid infinite loops. Your suggestion on createMemo does not fit my use case. My effect is the following:
createEffect(() => {
options().length > 0 ? openSelect() : closeSelect()
})
Thank you25 Replies
This sounds like a use case for https://primitives.solidjs.community/package/memo#createwritablememo
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
it's actually safe to update signals in an effect.
The reason there was that "warning" is to prevent people from doing an accidental update recursion, where an effect might be indirectly tracking a signal that it is supposed to update.
Update recursions are pretty bad, but isn't the whole point of avoiding signal updates in effects the fact that they trigger rendering twice? Also when dealing with transitions, effects dont run until the end of the transition, whereas memos run immediately.
yeah it has nothing to do with rendering
the template on their own is a completely independent effect. If anything, re-rendering is just a byproduct of the recursion
Oh I see now what you're saying with update recursion. My brain went to infinite loops for some reason, but ofc recursion can stop and still be bad đź‘Ť
I mentioned rendering simply because that's by far the most common effect, but you're right, nothing to do with rendering.
Thank you for your suggestion, but in that case I'll not have a setter for "open" because it is a derived value from the options signal (which is made with createResource). I need the setter so I can use it on other events like input focus and blur.Don't know if I'm doing this right, but that's how I see the problem.
Thank you all for your help.
I guess I'll use createEffect carefully trying to avoid any circular references.
After a few attempt to re-wire things I came up with a cleaner solution and avoid using createEffect.
I'll share my solution, in the hope to help someone rethinking their signal dependencies.
you can format block of code with tsx
<MyComponents options={optionsSignal()}/>
tsx
function MyComponent(props) {
const [focused, setFocus] = createSignal(false)
const opened = () => props.options && props.options.length > 0 && focused()
return (
<div>
<input onBlur={() => setFocus(false)} onFocus={() => setFocus(true)} />
<div class={setClassesWhen('list', opened, 'is-open is-focused')} role="listbox">
<For each={props.options}>{(value, idx) => <div data-id={idx()}>{value}</div>}</For>
</div>
</div>
)
}
<Suspense>
<MyComponent options={optionsResource()}/>
</Suspense>
``
could u show implementation of
setClassesWhen`? probably can be simplified too.Ty for the review
Just one thing. If you use optionsResource() as a prop, what's the problem on destructuring it inside the component? It's just a value, it will make no harm to the solid reactive system, right?
you mean your original approach?
No, I mean your review
your original approach would have been reacting when the resource resolves.
if you would destructure inside the component in my example, the component would not be reacting on the changes.
to get an intuition why that is the case, i highly recommend watching https://www.youtube.com/watch?v=cELFZQAMdhQ
SolidJS
YouTube
Intro to SolidJS reactivity (in 5 minutes)
An introduction video that walks you through Solid's reactivity in under 5 minutes.
But you're calling it
you talk about
right?
My doubt is that, if you're calling "optionsResource()" it will be a value not a signal, what am I missing here?
the trick is that props are getters
so it's like
the playground is handy if you want to know more about the props-transform.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
so when you do
props.options
you are actually calling a function, which is why you should only access the prop in effectful places and not destructurehummm, I'm not seeing the props as getters on the playground... IDK
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
ok, now I see it, ty đź‘Ť
if you press the output-tab you can see the result of the compilation
Thank you for the enlightenment guys!