-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
Describe the bug
Hi all,
I have a svelte/svelte kit application in which users can fill in a form by inputting data in various fields. The fields can be text area, radio button or check boxes. I recently migrated from Svelte 4 to 5 and I am experiencing a strange bug that seems to only affect Firefox (works fine with Chrome and Edge). The variables declared with $state used for keeping track of the user inputs are not "cleared" upon refreshing the page. This leads to discrepancies between the data displayed to the user and the data coming from the database.
Background on the application:
When the user goes to the form page, the load() function retrieves from the database the data inputted/stored previously (if any) and renders it in the respective fields of the form. The user can then modify the fields, and press a Save button which triggers an API call to store the data in the database.
The issue:
With Firefox (latest, 141.0), if the user modifies a field (any fields) and refreshes the page without saving, the newly inputted data will persist in the field even after the refresh. This is not the data stored in the DB. This is not intended behavior.
Note: This behavior is only observed when refreshing the page twice or more. When navigating away from the page and coming back, the data is loaded anew and displayed accurately.
Expected behavior:
Refreshing the page without saving should be a way for the user to discard all unsaved changes in fields at once. Any unsaved data should be removed and only the data retrieved from the DB should be displayed. This works as expected in Edge and Chrome.
Analysis:
It seems that the variables declared with "$state" keep the values that were provided by the user before refreshing.
//########################
// ### +page.server.js ###
//########################
// the load function queries the database and the values of the form's fields are returned to the
// frontend in an object. The object returned contains an object called "form" with these values,
// as well as other information not relevant in this context.
return {
form,
…(other data)
}
//####################
//### +page.svelte ###
//####################
// The object is retrieved and I declare the following:
let { data } = $props()
let form = $state(data?.form);
// I then pass this form object as a prop to a component called Form:
<Form
{form}
…(some other props)
/>
//###################
//### Form.svelte ###
//###################
// I get the data as props:
let {
form
… (other things)
} = $props()
// I then retrieve all the possible fields that may or not have values, depending on the information previously
// inputted and saved by the user:
let field1 = $state(form?.field1)
let field2 = $state(form?.field2)
…
// I declare them as $state since I want to be able to know when the user edit one of the fields, so that I can
// display a "Save" button. I then pass the different variables (eg, field1) to their respective field to be displayed
// in the form page. I created different components depending on the type of input required for each field.
// For example, I have a component called Textarea for a user to input text:
<Textarea
bind:value={field1}
… (other things)
/>
// I bind the value so that the user input in the textarea (value) can travel from the child (Textarea.svelte) to
// the parent (Form.svelte). When the user clicks on the save button, it will fire a onSave() function with a custom
// fetch API declared in Form.svelte, to save the data in the DB.
//######################
//### Texarea.svelte ###
//######################
let {
value = $bindable(),
…(other things)
} = $props();
…
<textarea
bind:value
></textarea>
Reproduction
- I provided
$inspect(field1)
in Form.svelte - I go to the form page for the first time (i.e., a blank form, no input yet submitted), the console in the browser displays
init undefined
. I do not input anything. I refresh a couple of times, the console displays the same. This is expected. - I then input some letters (e.g., "aaa") in the textarea, the console displays
update aaa
. This is expected. - I now refresh the browser without saving: The page refreshes, however the textarea contains already "aaa" and the console displays:
Init undefined
Update aaa
This behavior is unexpected. The field is correctly initialized as undefined, but then is updated to the previous value inputted which was not saved. I expect the textarea to be empty like before and the console to only display "init undefined".
The same happens with any type of inputs, whether textarea, radio button or check boxes: Whatever is clicked/inputted, it persists.
Only navigating away and coming back to the page seems to "reset the $state".
Does anyone have ideas on how to solve this issue? Is this a browser issue or state management issue? How can I force to "reset the states" so that the values are not kept between refresh?
Logs
System Info
Firefox (141.0)
Chrome (138.0.7204.169)
Edge (138.0.3351.109)
Win 11 pro
Severity
blocking an upgrade