-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Bug: functional components are not re-rendered if the provided props look the same #19104
Comments
This works just fine. If you call |
even on a functional component? It is not a class component or a pure component. |
In your example, as you set state for the hook to be just the same value, it just doesn't trigger any rerendering on any component at all. But if you add another useState hook to count rendering time and increase it in const [state,setState] = React.useState("")
const [,setRenderCount] = React.useState(0)
const update = val => {
setRenderCount(i => i + 1)
if(val === 'aaa') return setState('aa')
setState(val)
} This's probably new information for you and you might find it useful to make whatever you need. |
Hello @illuminist , thanks for providing a workaround. The thing is that I can not rely on the parent component state. Will that work if I add the sate on the Input itself? On my experience, it worked but I don't know if that is expected. |
Should be better to rely on change event instead as it has an access to the input element can manipulate its cursor directly. Main reason is because of state doesn't change, there is no reason for a component to re-render. Maybe have another internal state for displaying while keep true value in parent state. But I don't know your real use case. |
Hello @illuminist , my use-case is an input field that auto-formats as the user types. Because the auto formatting there are situations where the resulting value after user-input + format has not changed (for example, the user inputs a comma, and after auto format instead of |
So that you should have 2 state: one for display, and another for actual value. The display one should be internal state, and actual value is in parent component. Mainly, because of input event will report its value, in this case, the display state. So in value change handler, you have to find a way to convert display value into actual value (or formatted value into actual value) for example: converting string "10,000" into number 10000. Then your component reports 10000 back to parent component and save "10,000" as its internal state. This way, even user inputs "10,000.00", the parent component will have same 10000 actual value, but input component will have "10,000.00" to display. |
You're probably referring to the experimental version of hooks where React didn't bail out when it saw identical states. This was changed in #14569 and is documented under "Bailing out of a state update". This means your If you're referring to If you rely on the component re-rendering on identical state values you can either switch back to class components or wrap the state value in an object e.g. |
On previous versions of react, functional components were always re-rendered unless they were memoized. With the latest version, if the props do not change the component does not re-render. While this is an improvement in general, there are certain scenarios where you want to force a re-render, for example to react to some user input that does not change the value, but requires to make operations on the dom. A great example is an input field, where you may need to reposition the cursor even if the input content is the same
React version: 16.13.0
Steps To Reproduce
a
Link to code example:
https://codepen.io/danielo515/pen/KKVdmye?editors=0010
The current behavior
The component does not get re-render if the provided props do not change, even if there is a useEffect hook inside.
The expected behavior
The functional component should re-render unless it is memoized, or at least take in account if there is an use effect hook.
While this may look stupid from the provided example, imagine a controlled number input that automatically formats the user input, adding two decimal positions at the end
.00
. When the user reaches the dot, he/she may expect to input a dot and let the cursor move after the existing one, however, because the final value hasn't changed (there text still ends at.00
thanks to automatic formatting) the component is not re-rendered, making impossible to re-position the cursor using useEffect hook.As a workaround, you can add an use-state hook inside the controlled component, so you can store there the raw user input, but that only works until the user tries to input a value that doesn't change the internal state.
The text was updated successfully, but these errors were encountered: