#When updating signal in parent component, child components don't update.

33 messages · Page 1 of 1 (latest)

last sleet
#

I posted this on discussions earlier but I figured it would be better to ask here for support.

Here is the code I am using in my main file:

const [loaded, setLoaded] = createSignal(false);
const RR: Component<ParentProps> = ({ children }) => (<RestrictedRoute loaded={loaded()}>{children}</RestrictedRoute>);

Here is the code in my RestrictedRoute component:

const RestrictedRoute: Component<ParentProps<{ loaded: boolean }>> = ({ loaded, children }) => {
    if (!cookie.get('token')) loaded = true;
    if (!loaded) return <Loader/>;
    if (loaded && !store.user) return <Navigate href={'/'}/>;
    return children;
};

When the component RestrictedRoute is first mounted, the loaded signal is false in the parent component. But once the parent component updates the signal 'loaded' to be true, RestrictedRoute does not update and render the children. It still shows the loader as if the signal is still set to false.

I am pretty new to SolidJS so any help would be appreciated, thanks.

trim musk
last sleet
trim musk
last sleet
#

Thank you

trim musk
#

Happy to help 😃

last sleet
# trim musk Both destrucuring props and an early return break reactivity. You should not des...

When changing my RestrictedRoute component to this:

if (!cookie.get('token')) loaded = true;

return (
    <Switch fallback={<Loader/>}>
        <Match when={loaded && !store.user} keyed>
            <Navigate href={'/'}/>
        </Match>
        <Match when={loaded && !!store.user} keyed>
            {children}
        </Match>
    </Switch>
);

It appears I am having the same problem as before where the loader will not go away but the loaded state is true.

Is there something I missed?

trim musk
#

You're probably still destructuring the function props. For components, always use props as the argument and access from there, i.e. props.loaded || cookie.get('token').

#

I would probably structure it like this:

const App = (props) => (
  <Show when={cookie.get('token') || props.loaded} fallback={<Loader />}>
    <Show when={store.user} fallback={<Navigate href="/" />}>
      {props.children}
    </Show>
  </Show>
);
last sleet
#

so doing ({ prop1, prop2 }) => is bad?

trim musk
#

This will break props reactivity.

#

So if you only want to render once + static, it's ok, otherwise, it is bad.

#

Because props is an object with getters.

last sleet
#

so is it better to use multiple <Show> components or better to <Switch> multiple states?

trim musk
#

That depends. If the conditions are not mixed, but different, Switch/Match is simpler, but if they build on one another, multiple Show might be better.

In your case, it would look like that:

#
<Switch fallback={children}>
  <Match when={!props.loaded && ! cookie.get ('token')}>
    <Loader />
  </Match>
  <Match when={!store.user}>
    <Navigate href="/" />
  </Match>
</Switch>
#

But that would put the main case in the fallback, which I find confusing.

last sleet
#

yeah putting the main case as a fallback does not make much sense

trim musk
#

That's why I would choose double show for that case 😉

last sleet
trim musk
#

Good news is, both is extremely performant.

#

Props only have a getter, no setter.

last sleet
#

so then i would just add the cookie check to the first match statement?

trim musk
#

And if you would const isLoaded = props.loaded ..., this would break reactivity again.

last sleet
#

reactivity is annoying

trim musk
#

If you want to derive something from props, do so in a function to remain reactive.

#

const loggedIn = () => props.loaded || cookie.get('token');

#

And then use that function.

#

Once you got the hang of it, you'll enjoy reactivity.

#

Because it puts you in full control about what happens, you don't have to fight the framework.

#

Hope that helps you.

last sleet
#

I will take a look at it when I get home