Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After refreshing the page, it shows the initial value #49

Open
qdwang opened this issue Mar 26, 2024 · 8 comments
Open

After refreshing the page, it shows the initial value #49

qdwang opened this issue Mar 26, 2024 · 8 comments

Comments

@qdwang
Copy link

qdwang commented Mar 26, 2024

import { persistentAtom } from '@nanostores/persistent';
import { useStore } from '@nanostores/solid';

export const $foo = persistentAtom('foo', 1, {
    encode(x) {
        return x + ''
    },
    decode(x) {
        return parseInt(x)
    }
})
export const setFoo = x => {
    $foo.set(x)
}

export default function () {
    const foo = useStore($foo);

    return (
        <>
            <div>Foo: {foo()}</div>
            <button class="button is-small" onClick={() => setFoo(foo() + 1)}>Increment foo</button>
        </>
    );
}
  1. First, let's click the Increment button for 4 times, now the foo value is displayed a number 5.
  2. Now refresh the page, the foo value will be displayed a number 1.
  3. Click the Increment button.
  4. The foo value displays a number 6.

The second step is wrong, after refreshing the page, it should display a number 5.

Don't know if I was using it correctly.

@ai
Copy link
Member

ai commented Mar 26, 2024

The code looks good.

Maybe we have problem in Solid’s useStore? Can you try the same example with React or vanilla JS?

@qdwang
Copy link
Author

qdwang commented Apr 4, 2024

It returns the correct value by accessing $foo.get() on the loading of the component.

export default function () {
    const foo = useStore($foo);

    console.log(foo())  // correct
    console.log($foo.get()) // correct
    createEffect(() => {
        console.log(foo()) // correct on every increment
    })

    return (
        <>
            <div>Foo: {foo()}</div>
            <button class="button is-small" onClick={() => setFoo(foo() + 1)}>Increment foo</button>
        </>
    );
}

@ai
Copy link
Member

ai commented Apr 4, 2024

It returns the correct value by accessing $foo.get() on the loading of the component.

Let’s create issue in @nanostores/solid if so

@Fryuni
Copy link

Fryuni commented May 1, 2024

It might be because peristentAtom only reads the persisted value into the atom once it is subscribed to. Any reads before that will get the initial value.

@nanostore/solid does a get before the subscribe so it will always render first using the initial value. I think calling setState during the initial rendering might be what is causing the problem, since there is no signal hooked yet to be updated, so it will render using what was first read.

I think this line:

let store = atom(initial)

Should be

let store = atom(storageEngine[name] ? decode(storageEngine[name]) : initial);

@tordeu
Copy link

tordeu commented Jul 2, 2024

I see the same behavior in astro.

import { useStore } from '@nanostores/preact'
import { text } from '../store';

export default function StoreInput() {

    const $text = useStore(text);
    console.log("text = ", $text);
    
    function read() {
        console.log("read ", $text)
        return $text;
    }

    return (
        <input
            value={read()}
            onInput={(e) => {
                console.log("update")
                text.set((e.target as HTMLInputElement).value)
            }} />
    )

}

(console.log statements and read() function are merely added to log the values to the console.)

I added two instances of StoreInput to an astro page. Data is synchronized between them as expected. But when going to a different page and then coming back, the initial value is displayed. In the console, I can see that read() is retrieving the correct value, though. It just looks as if no UI update is triggered afterwards.

In astro, the component works as expected when using the client:only directive, but not when using client:load.

@ai
Copy link
Member

ai commented Jul 2, 2024

I need somebody experienced in the framework for debug to find a reason.

@tordeu can you do a investigation?

@tordeu
Copy link

tordeu commented Jul 3, 2024

@ai I am new to astro, but interested in finding the problem. But I will happily investigate as far as I am able to.

I also created an issue for astro: withastro/astro#11401

@tordeu
Copy link

tordeu commented Jul 3, 2024

As mentioned in withastro/astro#11401 (comment), I retested #49 (comment) using react and it is working as expected, now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants