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

Hard refresh resets the page to its initial value #1714

Open
2 tasks done
snnsnn opened this issue Jan 15, 2025 · 2 comments
Open
2 tasks done

Hard refresh resets the page to its initial value #1714

snnsnn opened this issue Jan 15, 2025 · 2 comments
Labels
bug Something isn't working

Comments

@snnsnn
Copy link

snnsnn commented Jan 15, 2025

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

I've come across strange behavior, and I'm not sure if it's a mistake on my part, a bug, or expected behavior.

Issue Description

Hi, I've created a project that uses server functions to update the displayed value. The server functions work as expected—the new value is reflected on the page. However, when I refresh the page, the value reverts to its initial state (the value before the update). Interestingly, if I navigate away from the page and return via a link, the new value is displayed.

I'm confident that the server function updates the value on the server because visiting the page in a different browser shows the new value. However, when the page is loaded directly (e.g., by refreshing), the old value appears. When navigating to the page via a link, the behavior seems consistent with the updated value.

Steps to Reproduce

  1. Go to Authors and select an author (e.g., /author/1).
  2. Enter a new value into the input box under "Update value using Server Function."
  3. Click Save. The new value should be displayed.
  4. Refresh the page. The old value reappears.
  5. Click the Authors link, then navigate back to the page. The new value should be displayed.
  6. Directly visit /author/1. The new value should also appear.
  7. Refresh the page. The old value is displayed again.

Additional Observations

Out of curiosity, I created an API endpoint to update the value and observed the following behavior:

  • When the page is refreshed, the value fetched from the server is displayed.
  • When navigating back to the page, the value updated via the server action is displayed.

When I update the value via an API call, refreshing the page shows the updated value. This is expected since the API call doesn't trigger a UI update directly. However, I assumed that using reload or revalidate would update the UI layer, but this doesn't seem to be the case. Perhaps I'm misunderstanding how these functions are intended to work.

Repository and Demo

Code for Reference

Here is the code for the page where the issue occurs:

const handleSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = async (event) => {
  event.preventDefault();
  const formData = new FormData(event.target as HTMLFormElement);
  const id = formData.get('id') as string;
  const name = formData.get('name') as string;
  await fetch(`/api/authors/${id}`, {
    method: 'POST',
    body: JSON.stringify({ name }),
  });
  return revalidate(queryAuthor.keyFor(author()?.id!), true);
  // throw reload({ revalidate: queryAuthor.keyFor(author()!.id) });
};

Here is the author/[id].tsx page:

import { Title } from "@solidjs/meta";
import { RouteDefinition, RouteSectionProps, action, createAsync, reload, revalidate } from "@solidjs/router";
import { JSX, Show } from "solid-js";
import { queryAuthor } from "~/api";
import { setStore, store } from "~/store";

export const route = {
  preload: ({ params }) => {
    queryAuthor(params.id);
  },
} satisfies RouteDefinition;

export default function Author(props: RouteSectionProps) {
  const author = createAsync(() => queryAuthor(props.params.id));

  const updateAuthorAction = action(async (formData: FormData) => {
    "use server";
    const id = formData.get('id');
    const name = formData.get('name') as string;
    if (id && name) {
      const index = store.authors.findIndex(item => item.id === id);
      if (index >= 0) {
        setStore('authors', index, prev => ({ ...prev, name }));
      }
    }
  });

  const handleSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = async (event) => {
    event.preventDefault();
    const formData = new FormData(event.target as HTMLFormElement);
    const id = formData.get('id') as string;
    const name = formData.get('name') as string;
    await fetch(`/api/authors/${id}`, {
      method: 'POST',
      body: JSON.stringify({ name }),
    });
    return revalidate(queryAuthor.keyFor(author()?.id!), true);
    // throw reload({ revalidate: queryAuthor.keyFor(author()!.id) });
  };

  return (
    <Show when={author()} fallback={<div>Author not found!</div>}>
      <Title>{author()?.name}</Title>
      <h1>{author()?.name}</h1>
      <div>
        <h2>Update Using Server Function</h2>
        <form action={updateAuthorAction} method="post">
          <input type="hidden" name="id" value={author()!.id} />
          <input type="text" name="name" value={author()!.name} />
          <button type="submit">Save</button>
        </form>
        <h2>Update Using API Call</h2>
        <form onSubmit={handleSubmit} method="post">
          <input type="hidden" name="id" value={author()!.id} />
          <input type="text" name="name" value={author()!.name} />
          <button type="submit">Save</button>
        </form>
      </div>
    </Show>
  );
}
@snnsnn snnsnn added the bug Something isn't working label Jan 15, 2025
@peerreynders
Copy link

@snnsnn
Copy link
Author

snnsnn commented Jan 16, 2025

FYI: https://discord.com/channels/722131463138705510/1329212362275684392

Thank you so much for your help in debugging the issue. Your explanation about how the server utilizes multiple workers for various capabilities really clarified the problem. It seems that the "Update value using Server Function" created an entirely new store in a different worker and updated that.

Reflecting on the issue I opened, it is the textbook definition of data inconsistency across multiple workers. The docs should emphasize this behavior. Reading directly from a file and writing to it solved the issue. Turns out it’s not only that—the failing of the revalidation call after API updates was also tied to this issue. With the new logic, this now works as expected. Probably, revalidation was working as expected but was using the stale data.

I wonder what the source of this behavior is—Nitro maybe? It would be great if they discussed the underlying architecture more or provided guidance to help people avoid running into these kinds of issues, saving time and frustration.

To the maintainers: I’ll keep this issue open in case others encounter similar problems, but feel free to close it if you think that’s appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants