React组件状态丢失:点击刷新后Input 2值被重置
React输入框组件状态丢失问题分析与解决
问题描述
我正在开发输入框组件MyInputField,采用三种不同方式渲染。点击刷新按钮后,Input 1和Input 3的值可保留,但Input 2的值每次都会被重置,刷新后第二个输入框的值为空。
代码示例
index.js
import React, { useState } from "react"; import ReactDOM from "react-dom"; import MyInputField from "./MyInputField"; import "./styles.css"; const Method3 = () => { return ( <div> <span>Method 3</span> <MyInputField /> </div> ); }; function App() { const [counter, setCounter] = useState(0); const method1 = () => { return ( <div> <span>Method 1</span> <MyInputField /> </div> ); }; const Method2 = () => { return ( <div> <span>Method 2</span> <MyInputField /> </div> ); }; return ( <div className="App"> <div>{method1()}</div> <Method2 /> <Method3 /> <button onClick={() => { setCounter(counter + 1); }} > Refresh me </button> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
MyInputField.js
import React, { useState } from "react"; const MyInputField = () => { const [value, setValue] = useState(""); return ( <input value={value} onChange={(e) => { setValue(e.target.value); }} /> ); }; export default MyInputField;
原因分析
核心在于React的组件实例复用规则:React通过组件类型和在父组件中的位置判断是否复用已有组件实例。
- Input 1对应的
method1是普通函数,每次App重渲染时,它返回的JSX结构中MyInputField的位置固定,React会复用该组件实例,状态得以保留。 - Input 3对应的
Method3是定义在App外部的独立组件,组件类型稳定,React会复用Method3实例及其内部的MyInputField实例,状态保留。 - Input 2对应的
Method2是定义在App组件内部的函数组件,每次App重渲染时,这个组件定义都会被重新创建,相当于全新的组件类型。React会卸载旧的Method2实例并创建新实例,内部的MyInputField也会被重新初始化,导致状态丢失。
解决方案
将Method2的定义移到App组件外部,让它成为稳定的组件类型,避免在组件内部动态定义组件:
修改后的index.js
import React, { useState } from "react"; import ReactDOM from "react-dom"; import MyInputField from "./MyInputField"; import "./styles.css"; const Method3 = () => { return ( <div> <span>Method 3</span> <MyInputField /> </div> ); }; // 将Method2移到App组件外部 const Method2 = () => { return ( <div> <span>Method 2</span> <MyInputField /> </div> ); }; function App() { const [counter, setCounter] = useState(0); const method1 = () => { return ( <div> <span>Method 1</span> <MyInputField /> </div> ); }; return ( <div className="App"> <div>{method1()}</div> <Method2 /> <Method3 /> <button onClick={() => { setCounter(counter + 1); }} > Refresh me </button> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
修改后,三个输入框的状态在点击刷新按钮后都能正常保留。
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

