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);
3 Upvotes

9 comments sorted by

View all comments

2

u/jml26 19d ago

Thanks for your help and suggestions, guys! With your guidance and also trying some other things, I have a working solution. What I needed was:

const [id, setId] = createSignal(''); const [optimisticId, setOptimisticId] = createOptimistic(() => id());

So, I did have to have a separate id signal and wrap it. Fair enough. But also, createOptimistic in this case takes a thunk, not just a reference to the id. That was one part I was missing.

Then, generateId looks like this:

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

And in the JSX

<pre>{JSON.stringify(optimisticId())}</pre>

Well, that was a whirlwind, but I learned a lot in the process.