QwikDev / qwik

Instant-loading web apps, without effort
https://qwik.dev
MIT License
20.7k stars 1.29k forks source link

[🐞] value attribute is remove on SPA navigation #4616

Open GrandSchtroumpf opened 1 year ago

GrandSchtroumpf commented 1 year ago

Which component is affected?

Qwik Runtime

Describe the bug

I've got something like that :

const Slider = component$((props: SliderProps) => {
  return <input type="range" min={props.min} max={props.max} name={props.name} value={props.value}/>
})

When I log the input after navigation with :

As you can see the value attribute has been removed. This is an issue when I use form.reset().

With the anchor the reset put the initial value With the Link the reset put the default value (which seems to be 50 for some reason with a range).

Reproduction

https://qwik-playground.vercel.app/form/

Steps to reproduce

In the link about you can click "cancel" to trigger the reset event. When you arrive on the page if you click "cancel" the controls will reset to initial value. When you navigate on the page with links, and click on "cancel" you'll see all controls reset to default value (except some where reset has been overwritten).

System Info

System:
    OS: Windows 10 10.0.22623
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 20.74 GB / 31.71 GB
  Binaries:
    Node: 18.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 3.3.1 - C:\Program Files\nodejs\yarn.CMD
    npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22621.1095.0), Chromium (114.0.1823.58)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    @builder.io/qwik: 1.1.5 => 1.1.5
    @builder.io/qwik-city: 1.1.5 => 1.1.5
    undici: 5.21.0 => 5.21.0
    vite: 4.3.9 => 4.3.9

Additional Information

The qwik.new stackblitz doesn't work anymore for me which makes it hard to provide a minimal example....

diecodev commented 1 year ago

Can you please share a repository with the code?

GrandSchtroumpf commented 1 year ago

Sure the page of the app above is here : https://github.com/GrandSchtroumpf/qwik-playground/blob/main/src/routes/form/index.tsx

diecodev commented 1 year ago

The problem that I find in your code is that you use the context of the form before, in the Slider component, if to this you add that the Link component does not allow that the current state changes, everything makes sense, because it does not let the context that you previously used in the Slider component mute its state to the one that you are placing now with the Form. I recommend you to use either two separate contexts or if you need 1 global context, then use in your store 2 objects, 1 to handle the context value of the slider and another to handle the context of the form.

P.S. about the link component you can find it in the link component documentation.

GrandSchtroumpf commented 1 year ago

@diecodev thanks for the response. I'm not sure to understand why the context would remove the value attribute from the HTML tag while keeping the min/max for example (see screenshot above).

I've tried removing the form context altogether to verify if it's that. I set the value with the props instead and the issue remains:

<Range name="range" class="outline">
  <legend>Select a range</legend>
  <ThumbStart value="10"></ThumbStart>
  <ThumbEnd value="80"></ThumbEnd>
</Range>

After anchor navigation: anchor navigation After Link navigation: Link navigation

diecodev commented 1 year ago

The min and max value come from the range context but the value come fron the form context, when you use the Range component you set the min and max value for the useFormValue hook (that return the useFormContext value) and you never pass the value to the range context (take a look to the Range compoennt). In the ThumbStart and the ThumnEnd components you read props.value (never pass in the Form page) thet one come fron useFormValue (that one can not be overwritting because you are using the Link component and the same context was used in the playground page)

So, you are using the nullish coalesing operator and this is the logic behind:

const value = props.value // not passed to the component
?? initialValue // that already have a value, so this is true and this is the value to assign to the value const
GrandSchtroumpf commented 1 year ago

I'm sorry, I think using the Range as an example is not a good way to display the problem. It actually happens to all controls. Let's let a look at the Input. I've updated the code to comment out the context, so we can see it's not an issue with the context. I use the props.value instead.

Scenario 1: use anchor navigation

  1. Go to https://qwik-playground.vercel.app/form/
  2. Open console and see that value is set on the input
  3. Click "cancel" the first input remains the same

Scenario 2: use Link navigation

  1. Go to https://qwik-playground.vercel.app
  2. Click on "form" on the left navigation
  3. Open console and see that value is not set on the input
  4. Click "cancel" the first input is cleared
diecodev commented 1 year ago

@GrandSchtroumpf Sorry for my nonsense answer, I see what you mention and apparently, the Link component has a strange behavior, if you add a console.log in your code in the range component you will see it on the browser and not on the server. I guess it is a bug to be seen by the qwik team as such. Sorry for the inconvenience.