how to manage global signals interacting with other global signals properly?

Im an ex react dev (pre-nextjs takeover) and have been out of the game for a while. came back to learn solid as it appears to solve my then frustrations with react. Specifically, the crux of this question: handling of global state. My very basic understanding is to use signals simply outside of component scope. and contexts for more complex interactions. My issue however, begins when attempting to do something like the following: - have a globally scope signal that tracks the data in a popup. - want the popup to animate disappearing when the signal goes null, and as such, need the last known non null state. - create a signal that tracks the last non-null data so it can be rendered animating away. - create an effect like the following:
const [popup_data, set_popup_data] = createSignal(null);
const [last_popup_data, set_last_popup_data] createSignal(null);

createEffect(() => {
if (popup_data() !== null) {
set_last_popup_data(popup_data());
}
});
const [popup_data, set_popup_data] = createSignal(null);
const [last_popup_data, set_last_popup_data] createSignal(null);

createEffect(() => {
if (popup_data() !== null) {
set_last_popup_data(popup_data());
}
});
- this results in a (mostly understandable) warning about the effect not being able to be disposed of properly. I understand that it is global, and, as such, wont be disposed of (like an effect in a component will be). This is my intention, and the presence of this warning tells me im likely approaching things non idiomatically. What is the better (or- more "solid.js") approach to a system where one global signal needs to have an effect on another global signal? I can think of a few solutions but they all feel like workarounds. for example, placing all the global effects inside the unchanging root component.
13 Replies
TaQuanMinhLong
You can take a look at using createEffect with on, this already has built-in previous state tracking https://docs.solidjs.com/reference/reactive-utilities/on-util
⯁ 𝓥𝓪𝓵𝓮𝓻𝓲𝓮
while i appreciate that, as i havent seen it before, i understand that there are solutions to this particular example, however, my question is about the broader concept of global signals interacting with other global signals. the example is meant to show two global signals needing interaction, as opposed to the specific use case. apologies if that was unclear and to be clear, it may entirely be the case that this simply isnt supported within solid. having helpers to get past things like previous state tracking might be the reality of the situation. "State must be atomic, never influenced by other state outside of a component." Id find it cumbersome, but it'd be reasonable of a framework to make a choice like that.
REEEEE
REEEEE4w ago
The warning is just for informing you that the effect won't be disposed and could lead to some sort of memory leak if you don't know what you're doing AFAIK. Having said that, there is no real issue with doing this and many people prefer to do global signals. Personally, I prefer to encapsulate this sort of information in a context provider if you're going to end up needing to use this in multiple places either a single instance or to create multiple instances
TaQuanMinhLong
Just make a store instead, so you can interact as many signals as you need
⯁ 𝓥𝓪𝓵𝓮𝓻𝓲𝓮
@REEEEE is there a way to tell solid to not emit the warning then? like i said, my intention is global state, at the root module which gets loaded in once. Im hesitant to reach for contexts as (to me, for what i tend to do) it seems like a heavy hammer for a small nail. The moment i reach for some type of abstraction (like you said having multiple instances of something), contexts to me make a lot more sense
REEEEE
REEEEE4w ago
The simplest way is to wrap it in a createRoot
⯁ 𝓥𝓪𝓵𝓮𝓻𝓲𝓮
@TaQuanMinhLong i havent interacted at all with the store yet. ill have to look into it more to understand 🙂
TaQuanMinhLong
Just do it 🤣
⯁ 𝓥𝓪𝓵𝓮𝓻𝓲𝓮
OH suddenly what ive read online makes so much more sense. so for context: I have one file for simply loading in the page, that then reaches out to the main "App" component. I thought people were saying to throw state somehow inside of that call in there, but i think what you're saying, is that, there can be many roots, and have their own effects within? with ability to use a signal across both roots? as a result, any file which declared some global signal, need only wrap its effects in a root, solely for mutating that state?
REEEEE
REEEEE4w ago
You could also wrap the whole state as well and return the signals from the root so something like
const [signal, setSignal] = createRoot((dispose) => {
const [mySignal, setMySignal] = createSignal(0)

createEffect(() => ...do something)

return [mySignal, setMySignal]
})
const [signal, setSignal] = createRoot((dispose) => {
const [mySignal, setMySignal] = createSignal(0)

createEffect(() => ...do something)

return [mySignal, setMySignal]
})
⯁ 𝓥𝓪𝓵𝓮𝓻𝓲𝓮
yes, this seems so much more reasonable to me. this way, i can have global state wherever i need it to across files, with locality of behavior. and still ensure solid knows that these roots are globally scoped
REEEEE
REEEEE4w ago
yup
⯁ 𝓥𝓪𝓵𝓮𝓻𝓲𝓮
absolutely incredible. many thanks
Want results from more Discord servers?
Add your server