facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
227.32k stars 46.37k forks source link

Bug: [React Refresh] Unexpected behavior when adding/removing elements prior to uncontrolled inputs #27933

Open lawrencecchen opened 8 months ago

lawrencecchen commented 8 months ago

React version: 18.2.0

Steps To Reproduce

https://github.com/facebook/react/assets/54008264/94e69206-48a1-4064-a89c-583aadcd8269

  1. https://stackblitz.com/edit/vitejs-vite-cswk6t?file=src%2FApp.tsx
  2. Enter 1, 2, 3, and 4 respectively in each textbox
  3. Comment and uncomment the <br /> and save
function App() {
  return (
    <>
      <div>
        {/* COMMENT AND UNCOMMENT THIS BR AND SAVE */}
        <br />
        <input type="text" />
        <input type="text" />
        <input type="text" />
        <input type="text" />
      </div>
    </>
  );
}

export default App;

Link to code example:

https://stackblitz.com/edit/vitejs-vite-cswk6t?file=src%2FApp.tsx

The current behavior

Uncontrolled inputs' values are not synced correctly. (I tested with controlled inputs, and it worked properly.) I verified that this bug exists in Safari (Version 17.1 (19616.2.9.11.7)) and Chrome (120.0.6099.199). Tried in both Vite and Next.js, so I'm fairly certain it's a react refresh issue.

"@vitejs/plugin-react": "^4.2.1",
"next": "^14.0.3",

The expected behavior

Each input should keep its own value.

rickhanlonii commented 8 months ago

Yeah, this is because React doesn't know which input to associate with which slot. To fix, you can add a key to each input so React will re-order it instead of mutating the elements. See this for more info.

I'll leave open because ideally Fast Refresh wouldn't cause this.

rickhanlonii commented 8 months ago

@gaearon do you have thoughts on this, maybe I'm missing something?

afsalkhanmdt commented 8 months ago

image

Tried with key and worked fine.

v-rathour commented 8 months ago

hello lawrencecchen , why are you use this br tag at start of this page. By the way there is not need for this br tag . the value of the input box it change on each refresh page request .As we all know in react any change in directly not effected DOM rather than virtual DOM, then change reflect in DOM and refresh the page .this is main region of this problem so ignore the use of br tag in that place.

ANUGLYPLUGIN commented 8 months ago

I think that is because of react reconcile steps, without having key, loop compares corresponding element by tag. But <br /> tag is different from <input /> tag so the first element's dom is dropped and then you can see the input value move step 1.

alokprinc commented 8 months ago

Hi, Guys can you please point me in the right direction here, I have made some projects in React and I want to look into this issue. Where should I start looking for this issue?

yhekim commented 6 months ago

I think This behavior, "Uncontrolled inputs' values are not synced correctly," typically refers to an issue encountered when using uncontrolled inputs in React applications. This occurs when the values of input fields are not managed by React.

In React, there are two main ways to manage the values of input fields:

Controlled Inputs: In this approach, the values of input fields are stored in the state of a React component, and the state is updated on every change. The values are controlled and manipulated from the component's state.

Uncontrolled Inputs: In this approach, the values of input fields are directly stored in the DOM and are handled independently of the React component's state. They are typically accessed using refs.

The warning you mentioned may arise when using uncontrolled inputs. In such cases, since the values of input fields are not tied to the React state, synchronization of values cannot be ensured when the component re-renders or the page refreshes. This means that the component's state is not updated after the user enters data into the input field.

If the expected behavior is for "each input field to maintain its own value," this is typically not achievable when using uncontrolled inputs. Instead, it's more appropriate to use controlled inputs, where each input field's value is tied to the component's state. This ensures that each input field's value is maintained according to the component's state and is correctly synchronized.

Controlled Inputs Examples:

import React, { useState } from "react";

function App() { const [inputValues, setInputValues] = useState(["", "", "", ""]);

function handleChange(event, index) { const newInputValues = [...inputValues]; newInputValues[index] = event.target.value; setInputValues(newInputValues); }

return ( <>

{/*
*/} handleChange(e, 0)} /> handleChange(e, 1)} /> handleChange(e, 2)} /> handleChange(e, 3)} />
</>

); }

export default App; "In this way, each input field will maintain its own value and synchronize with the values in the component state."