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

Hooks - a little discrepancy between React and Preact #3175

Closed
1 task
kksidd opened this issue Jun 4, 2021 · 2 comments
Closed
1 task

Hooks - a little discrepancy between React and Preact #3175

kksidd opened this issue Jun 4, 2021 · 2 comments

Comments

@kksidd
Copy link

kksidd commented Jun 4, 2021

  • Check if updating to the latest Preact version resolves the issue

Describe the bug
Observed a little discrepancy in the behavior of 'useState' (and hence, by extension, also 'useReducer') hook in Preact as compared to React.

To Reproduce
Following codesandbox examples use the same code; the first one is in React while the second one uses Preact -
https://codesandbox.io/s/strange-wood-4lcnq?file=/src/App.js
https://codesandbox.io/s/festive-edison-s2js0?file=/index.js

The idea is to filter out numeric characters from the inputted text.
Relevant code being -

const App = () => {
  const [text, setText] = useState("");
  const handleChange = (event) => {
    let text = event.target.value;
    setText(text.replace(/[0-9]/g, ""));
  };

  return <input type="text" value={text} onInput={handleChange} />;
};

Steps to reproduce the behavior:

  1. Try entering "abc123" in the input
  2. React version filters out the numeric part and shows only "abc" while Preact fails to do so and shows "abc123"
  3. Add "xyz" to the already inputted value and now Preact filters out the numeric value to correctly show "abcxyz"

Expected behavior
It was expected that Preact, as with React, applied the filter whenever the input value changed.

What seems to be happening is that useState() first compares the new value with the existing one and updates (thus calls setState()) only if the values differ.

In the example code above, while the value as entered and displayed in the input does contain the numeric values, because the new (filtered) value remains the same as the saved value, setState() is not invoked and the text input appears to be out of sync with the saved state.

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Jun 5, 2021

This isn't a discrepancy in stateful hooks but more in how events/(un)controlled inputs work in Preact, let's look at this a bit deeper as to why it shows this unexpected behavior.

When we type into a text-field naturally it will just alter the value and disregard any value passed into it, i.e. the value is modified internally, hence why e.target, which is the input-node, carries an updated value property. When we re-render due to setting state then this value will correct itself before it appears on screen.

Here comes the tricky part, we type abc123 but we continuously update it to be abc which in Preact means that the update will be ignored. We currently don't support fully controlled components, I've got an open PR for this which needs more research, for the time being you can opt to set state like this: setState({ value: e.target.value }) as that can't bail out of updates.

Example: https://codesandbox.io/s/condescending-goodall-icrte?file=/index.js

Relevant explorative PRs:

@kksidd
Copy link
Author

kksidd commented Jun 5, 2021

Thanks for the clarification :)

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

No branches or pull requests

2 participants