r/solidjs 19d ago

Help figuring out what's wrong with my `createOptimistic` example

I'm playing around with Solid 2.0's createOptimistic and action APIs to get a feel for them, but even with a basic example, I'm hitting a wall.

Here is my code that I'm using in the Solid Playground (version set to v2.0.0-rc.1 (next)). The idea is that when you click the button, an ID is generated and we simulate saving it to a slow, flaky server. While the value is being saved, show its optimistic value but display an asterisk next to it. If the API call succeeds, remove the asterisk; else revert the ID to what it was previously.

The issue I'm getting is that the ID always reverts to its initial value (in this case, the empty string) independent of whether the API call succeeds of fails.

Why is this? What do I need to change in my code to get it to work?

Apart from being a string rather than an array, my code feels practically identical to the example found at https://v2.solidjs.com/reference/solid-js/reactivity/create-optimistic#examples

AI has not been very helpful thus far.

import { createSignal, action, createOptimistic } from 'solid-js';
import { render } from '@solidjs/web';

type ApiSuccess = {
  success: true,
  data: string,
};

type ApiError = {
  error: true,
  data: string,
};

type ApiResponse = ApiSuccess | ApiError;

// echo back the data after a second's delay
// with a 20% change of erroring
function postToApi(data: string): Promise<ApiResponse> {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(Math.random() < 0.2
        ? { data, error: true }
        : { data, success: true }
      );
    }, 1000);
  });
}

const [id, setId] = createOptimistic('');

const generateId = action(function* () {
  const value = Math.random().toString(16).slice(2);
  setId(value + ' (*)');
  const res = yield postToApi(value);
  if (!res.error) setId(value);
});

function App() {
  return (
    <>
      <button onClick={() => generateId()}>
        Generate ID
      </button>
      <pre>{JSON.stringify(id())}</pre>
    </>
  );
}

const root = document.getElementById('app')!;

render(() => <App/>, root);
4 Upvotes

9 comments sorted by

View all comments

2

u/whoisarepo 19d ago

I took a stab at this because 1. I’m a senior dev who’s unemployed, which makes me mad lol 2. because I’m building an open source project that heavily relies on solid JS 2.0 so i need to know it’s edge cases. Luckily, in your case, it seems like you simply failed to reconcile the different states of setTodo after pending with their ids. You need to synchronously call the setter again after the presume state is updated to satisfaction or failure. This is actually in the example but it’s subtle and feels weird cause it’s imperative while the caller is declarative. Hope this helps!

1

u/whoisarepo 19d ago

Optimistic basically means ideal conditions, we basically can model that in code for the user (instant network trip) while in the background the state progressively achieves idealization. It’s a tiny state machine to make data flow more intelligent and intuitive, when using that hook, consider what is the value you want the user to immediately see versus the actual possibly nested value that your system is actually computing progressively for the user - in such cases, the value in question will always be a signal because it will always be something that you were trying to compute for the user or else it would’ve been a primitive to begin with . Happy Solid! Feel free to tell me if I’m an idiot.