Skip to content

2.0.0-beta.30 | createStore with {ssrSource:"server"} and async store function is not awaited #2971

Description

@mizulu

Describe the bug

{ssrSource:"server"} with an async store function is not respected
and the clients sees an empty store on the initial render.

additionally the client side, runs the store function as well.

With a sync store function, this problem does not exists.
and works as expected. client first render is the server value
and no hydration causes the store to evaluate again client side. as part of the hydration.

Your Example Website or App

https://s.olid.uk/id/omIbsbbhQ-uQuTV6DID1rQ

Steps to Reproduce the Bug or Issue

sync store with {ssrSource:"server"} properly renders
the server value and does not run the store function client side when hydrating

however an async store, the ssr render does not await the store, and render nothing.
and does run the client side store function.

in the reproduction

sync store case

renders
Sync:fromServer

as expected, and does not update to the fromClient

async store case

renders
"Async:"

and after 4 seconds renders
"Async:fromClient"

instead of the expected:

  • fromServer renders from the ssr output, and do not run the client side function that updates its to fromClient
    same as the sync version.

Expected behavior

both async/sync store function should behave the same when using {ssrSource:"server"}
and render the initial server side value of the store.

Screenshots or Videos

Image

Platform

  • OS: [e.g. macOS, Windows, Linux]
  • Browser: [e.g. Chrome, Safari, Firefox]
  • Version: [e.g. 91.1]

Additional context

import { render, isServer } from '@solidjs/web';
import { createSignal, createStore, Loading } from 'solid-js';

export default function App() {

  const [s, ss] = createStore(() => {

    return { message: isServer ? "fromServer" : "fromClient" }
  }, { message: "Serv" }, { ssrSource: "server" })


  const [s2, ss2] = createStore(async () => {
    if (!isServer) {
      await new Promise(r => setTimeout(r, 4000))
    }
    return { message: isServer ? "fromServer" : "fromClient" }
  }, { message: "Serv" }, { ssrSource: "server" })


  const [count, setCount] = createSignal(0);
  return (
    <div class="p-2">
      <div>
        <b>Sync:</b>
        <Loading>
          {s.message}
        </Loading>
      </div>
      <div>
        <b>Async:</b>
        <Loading>
          {s2.message}
        </Loading>
      </div>
      <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={() => setCount(count() + 1)}>
        Count: {count()}
      </button>
    </div>
  );
}


if (typeof document !== 'undefined') {
  render(() => <App />, document.getElementById('root')!);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions