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

refactor: Rewrite Forms doc #1218

Merged
merged 1 commit into from
Jan 2, 2025
Merged

refactor: Rewrite Forms doc #1218

merged 1 commit into from
Jan 2, 2025

Conversation

rschristian
Copy link
Member

Follow up to the refs & context rewrites, trying to add clarity here too.

Of note:

  • Adds hooks examples
  • Shows forms via FormData
  • Adds a suggestion to not rely on component state for all inputs
  • Tries to expound the Controlled Component issue


> **Walk-Through:** Say we listen for a "change" event on a checkbox, which is fired when the checkbox is checked or unchecked by the user. In our change event handler, we set a value in `state` to the new value received from the checkbox. Doing so will trigger a re-render of our component, which will re-assign the value of the checkbox to the value from state. This is unnecessary, because we just asked the DOM for a value but then told it to render again with whatever value we wanted.
Copy link
Member Author

@rschristian rschristian Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://preactjs.com/guide/v10/forms#checkboxes--radio-buttons

I've read this through a dozen or so times and I'm still not quite sure what it is suggesting here. Using the updated state value from onChange & rerendering based upon it is unnecessary, so instead, invert the current state value (as it's just a toggle) and rerender with that instead? It's the same issue, just a different format (and one I'd argue is more problematic, as it allows component state to get out-of-sync with the DOM in some cases).

Not sure if that makes sense to anyone else, very, very possible I'm misunderstanding entirely, but I stripped this comment out as it seemingly makes little sense to me at the moment. I don't understand what it's advocating for or why that's an improvement.

Comment on lines +325 to +339
Preact has a known issue with controlled components: rerenders are required for Preact to exert control over input values. This means that if your event handler doesn't update state or trigger a rerender in some fashion, the input value will not be controlled, sometimes becoming out-of-sync with component state.

An example of one of these problematic situations is as such: say you have an input field that should be limited to 3 characters. You may have an event handler like the following:

```js
const onInput = (e) => {
if (e.currentTarget.value.length <= 3) {
setValue(e.currentTarget.value);
}
}
```

The problem with this is in the cases where the input fails that condition: because we don't run `setValue`, the component doesn't rerender, and because the component doesn't rerender, the input value is not correctly controlled. However, even if we did add a `else { setValue(value) }` to that handler, Preact is smart enough to detect when the value hasn't changed and so it will not rerender the component. This leaves us with [`refs`](/guide/v10/refs) to bridge the gap between the DOM state and Preact's state.

> For more information on controlled components in Preact, see [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) by Jovi De Croock.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to expound more on the controlled input issue, rather than jumping straight into "use refs", which I wrote before. I hope it's better? Basically trying to condense & transplant Jovi's writing.

Feedback on the wording here very much appreciated, as this is a bit of a prickly issue that users may run into.

@rschristian rschristian force-pushed the refactor/form-examples branch from 00ee620 to 3046b34 Compare January 2, 2025 08:42
@rschristian rschristian merged commit a68b1b2 into master Jan 2, 2025
5 checks passed
@rschristian rschristian deleted the refactor/form-examples branch January 2, 2025 20:22
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

Successfully merging this pull request may close these issues.

3 participants