Skip to content

2.0.0-beta-16 | optimistic update is not being rolledback when rendered from a derived store and a <For> #2864

Description

@mizulu

Describe the bug

source for llm https://source.s.olid.uk/id/QQXR8CMkT_2BW2vmZm0arg

open the repro, wait until all pending async are resolved
it will finally render

however the {"id":100} is an optimistic update of the store
that should have rolled back after the store was refreshed and resolved.

-
For
{"id":1}
{"id":2}
{"id":3}
{"id":4}
{"id":100}

The console logs

itemStore Resolver Start
Sleep:3s
itemStore Resolver ended
Sleep:1s
Refreshing itemsStore
optimistic new item with id 100
itemStore Resolver Start
Sleep: 3s
itemStore Resolver ended

Your Example Website or App

https://s.olid.uk/id/QQXR8CMkT_2BW2vmZm0arg

Steps to Reproduce the Bug or Issue

.

Expected behavior

it is likely that the call

    setItemsStore((s) => {
      console.log("optimistic new item with id", new_ids)
      return [...s, { id: new_ids++ }]
    })

in addAndLoad()

should only show while the refreshing is going on
once it is resolved, that item should have been removed.

Screenshots or Videos

No response

Platform

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

Additional context

import { render } from '@solidjs/web';
import { createSignal, createOptimisticStore, Loading, isPending, refresh, For } from 'solid-js';

export default function App() {
  async function sleep(ms = 1000) { 
    console.log("Sleep:", ms/1000 + "s")
    await new Promise(r => setTimeout(r, ms)) 

    }
  let base = [{ id: 1 }, { id: 2 }, { id: 3 }]
  let new_ids = 100;
  const [itemsStore, setItemsStore] = createOptimisticStore(async () => {
    console.log("itemStore Resolver Start")
    await sleep(3000)
   
    base = [...base, { id: base.length + 1 }]
    
    console.log("itemStore Resolver ended")
    return base
  }, [])

  const [mainStore, setMainStore] = createOptimisticStore(() => {
    return { theItems: itemsStore }
  }, {});




  async function addAndLoad() {

    await sleep(1000);
    console.log("Refreshing itemsStore")
    refresh(itemsStore)


 
    setItemsStore((s) => {
      console.log("optimistic new item with id", new_ids)
      return [...s, { id: new_ids++ }]
    })


  }
  setTimeout(async () => {

    addAndLoad()
  }, 5000)

  const [count, setCount] = createSignal(0);
  return (
    <div class="p-2">
      <Loading fallback={"Loading.."}>

        <div>

          {isPending(() => {
            return [...itemsStore]
          }) ? "ItemsStore Pending?" : "-"}

          <h1>For</h1>
          <For each={mainStore.theItems}>
            {v => {
              return <div>{JSON.stringify(v)}</div>
            }}
          </For>
        </div>

      </Loading>
      <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={() => (addAndLoad(), setCount(count() + 1))}>
       Click to add a new item: {count()}
      </button>
    </div>
  );
}


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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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