solidjs · GitHub

Hey! I'm learning Solid by migrating my small React app, and right off the bat I'm stuck a bit. This is my usual approach in React apps to manage auth layer: I check the storage for tokens, bootstrap the data and lunch app or redirect to sign-in.

I've tried to implement in Solid as is, but it doesn't work at all. Even though the bootstrap signal is updated, the render is not triggered. Even though the isBootstrapping is true initially, it becomes false in the DOM, but no render happens.

Me and ChatGPT 4 both are out of options, LLM is confident that this is a bug even.

Solid version: ^1.7.6

import { createSignal, createEffect } from "solid-js"
const AuthGuard = () => {
  const [isBootstrapping, setIsBootstrapping] = createSignal(true)
  const [isAuthed, setIsAuthed] = createSignal(false)
  createEffect(() => {
    const bootstrap = async () => {
      try {
        if (localStorage.getItem("accessToken") === null) {
          throw new Error("No access token")
        }
        await new Promise((resolve) => setTimeout(resolve, 1000))
        setIsAuthed(true)
      } catch (error) {
        setIsAuthed(false)
      } finally {
        setIsBootstrapping(false)
      }
    }
    bootstrap()
  })
  // this always renders as Loading... false
  if (isBootstrapping()) {
    return <div>Loading... {String(isBootstrapping())}</div>
  }
  if (!isAuthed()) {
    return <div>Not Authenticated</div>
  }
  return <div>Rendering App</div>
}
export default AuthGuard

Hey there !

I see where your issue comes from. This is a pure suggestion as I'm not able now to try the fix I came up with rn.

With Solid, a function's body is ran only one time. Thus, your if...else statement gets checked only when the component is built.

Then, Solid keeps track and updates only DOM elements whose value changed.

Thus, instead of going with:

if (isBootstrapping()) {
    return <div>Loading... {String(isBootstrapping())}</div>
}
if (!isAuthed()) {
    return <div>Not Authenticated</div>
}
return <div>Rendering App</div>

Use the Show component to set conditional to components visibility. Thus, your if...else statement becomes:

import { Show, [your solid-js imports] } fro…

View full answer

Hey there !

I see where your issue comes from. This is a pure suggestion as I'm not able now to try the fix I came up with rn.

With Solid, a function's body is ran only one time. Thus, your if...else statement gets checked only when the component is built.

Then, Solid keeps track and updates only DOM elements whose value changed.

Thus, instead of going with:

if (isBootstrapping()) {
    return <div>Loading... {String(isBootstrapping())}</div>
}
if (!isAuthed()) {
    return <div>Not Authenticated</div>
}
return <div>Rendering App</div>

Use the Show component to set conditional to components visibility. Thus, your if...else statement becomes:

import { Show, [your solid-js imports] } from "solid-js";
const AuthGuard = () => {
    [your component's logic]
    return (
        <Show when={!isBootstrapping()} fallback={<div>Loading... {isBootstrapping()}</div>}>
             <Show when={isAuthed()} fallback={<div>Not authenticated.</div>}
                 {/** Your app component goes here */}
             </Show>
        </Show>
    );
}

This is a better practice as Solid will handle visibility conditions updates through the when parameter and will update the UI visibility according to it.

Check this for more details: SolidJS Conditional UI Display.

1 reply

@novembrea

Hey, thanks so much! This was exactly the case, I also feel like understand Solid's reactivity better now 🎉

Read the original on github.com ↗