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

Hydration clobbers input into form #1755

Closed
ispyinternet opened this issue Sep 25, 2018 · 20 comments · Fixed by #11986 or #14349
Closed

Hydration clobbers input into form #1755

ispyinternet opened this issue Sep 25, 2018 · 20 comments · Fixed by #11986 or #14349
Assignees
Labels
Milestone

Comments

@ispyinternet
Copy link

ispyinternet commented Sep 25, 2018

If your form has just been server rendered and you initial bind the values to empty string, when a user starts to enter data into the form it will get clobbered by hydration.

You can disable the inputs until the page hydrates, but I like my site(s) to be snappy and don't want to block the form out until hydration, admittedly its not an eternity, but its enough for me to drag it to the table.

RH has indicated that if this were standard behaviour some use cases would present weird / unsuitable UX experience, for example typing into a search input doesn't result in the autocomplete dropdown appearing.

In which case I would like to request some optin behaviour to prevent hydration from clobbering the form inputs.

<input bind:value:nohydrate=username>

or something of that ilk?

@ispyinternet
Copy link
Author

To be fair, this is caused by an excessively large file, but where is that cutoff and what will be the demands of user apps?

@benmccann
Copy link
Member

Closing as a duplicate of #4308. This issue isn't specific to form input, but multiple elements that are negatively affected by being destroyed and recreated such as videos and animations

@hbirler
Copy link
Contributor

hbirler commented Jun 15, 2021

I feel that it might make sense to keep this as an separate open issue. I don't believe the cause is only destroying/recreating nodes but also calling set_input_value when mounting the elements. So even if we never destroy & recreate, form inputs will likely reset.

@andreasnuesslein
Copy link

andreasnuesslein commented Jun 13, 2022

Ticket #4308 is solved but the problem persists, where hydration removes the input that has been done up to this point.

@andreasnuesslein
Copy link

andreasnuesslein commented Jun 13, 2022

You can disable the inputs until the page hydrates,

@ispyinternet do you have a nice way of doing this? Or just some boolean variable that gets changed on "onMount"?

@andreasnuesslein
Copy link

@benmccann pinging you directly as you were the one closing this ticket. I still the problem described in this ticket still exists. Could you revive this ticket? :)

Cheers

@benmccann
Copy link
Member

@andreasnuesslein could you provide a minimal reproduction? Assuming the original case was addressed we will not have a way to reproduce otherwise

@andreasnuesslein
Copy link

@andreasnuesslein could you provide a minimal reproduction? Assuming the original case was addressed we will not have a way to reproduce otherwise

I still mean to create an example. I've only been out of business with the flu for the last 10 days :\ Slowly gettin' better.

andreasnuesslein added a commit to andreasnuesslein/svelte-ssr-issue that referenced this issue Aug 1, 2022
@andreasnuesslein
Copy link

I finally made an example @benmccann

https://github.com/andreasnuesslein/svelte-ssr-issue

Basically I created a new sveltekit project (npm init svelte svelte-ssr-reset-example) and modified the index.svelte and created the sleep.svelte. No other changes. The README.md contains the steps to reproduce.

@thoughtspile
Copy link

Second this, prepared a nearly identical repro: https://github.com/thoughtspile/svelte-hydration-repro

@istarkov
Copy link

Reproduced for me with latest svelte. Also it resets focus on input element too during hydration.

@andreasnuesslein
Copy link

One way or another @benmccann , I understand it's not on the top of the list at the moment, but could you please re-open this issue? It's just not solved yet.

Cheers

@janvogt
Copy link

janvogt commented Feb 21, 2023

This has been very frustrating experience for me as well, and should certainly be reopened. However, I'd like to share a workaround in the meantime.

During initialization, it is possible to set the bound variable to the browsers current element's value. Like so:

<script>
  let value
  if (document) {
   value = document.querySelector('input[name="x"]').value
  }
</script>

<input name="x" bind:value />

N.B.: I'm using this with bind:group in a sveltekit app and guard it with browser from $app/environment

@rmunn
Copy link
Contributor

rmunn commented Jul 10, 2023

In #8266 (comment) there was a suggestion for claiming <input> nodes during hydration that seems good to me; copying it here so that it won't get lost if #8266 is closed as a duplicate.

	input = claim_element(nodes, "INPUT", {});
	
	// When input is different from the context value
	if (input.value !== /*a*/ ctx[0]) {
		// We use the binding handler to update it's value
		/*input_input_handler*/ ctx[1].call(input).
	}

@thoughtspile
Copy link

We run this userland workaround in production, seems to do the trick with the caveat of not triggeing on:input:

<script context="module">
	const preHydrationValues = new WeakMap();
	// client-side only
	typeof document !== 'undefined' &&
		document.querySelectorAll('input').forEach((input) => {
			// only for changed inputs
			if (input.value !== input.getAttribute('value')) {
				preHydrationValues.set(input, input.value);
			}
		});
</script>

<script>
	export let value;
	function restorePreHydrationValue(node) {
		const savedValue = preHydrationValues.get(node);
		if (savedValue) {
			node.value = savedValue;
			value = savedValue;
			preHydrationValues.delete(node);
		}
	};
</script>

<input
	use:restorePreHydrationValue
	bind:value
	{...$$restProps}
/>

@pjb3
Copy link

pjb3 commented Nov 5, 2023

I also found this bug very frustrating and hard to diagnose. Seems like a huge gotcha that needs to be pointed out in the docs when using universal loading. My solution has to just been to not use universal loading at all and instead use server loading, but I am curious to know what other people building Sveltekit apps are doing and if this is viewed as a bug that plans to get fixed or what the recommended way of dealing with this is.

@benmccann
Copy link
Member

I think this will probably be addressed by Svelte 5, but am not positive. We should test when it's available

@pjb3
Copy link

pjb3 commented Nov 5, 2023

I think this will probably be addressed by Svelte 5, but am not positive. We should test when it's available

@benmccann That would be great, I'll test it out when it comes out

@Rich-Harris Rich-Harris added this to the 5.0 milestone Apr 2, 2024
@stalkerg
Copy link
Contributor

yes, it's a supper annoying issue, basically if user touch input before hydration is finished - it should be avoided by hydration.
It still race condition possible but it should significantly mitigate it.

@trueadm trueadm self-assigned this Jun 4, 2024
@andreasnuesslein
Copy link

🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment