保留和重置状态
状态在组件之间是隔离的。React 根据它们在 UI 树中的位置来跟踪哪个状态属于哪个组件。您可以控制何时保留状态以及何时在重新渲染之间重置状态。
您将学习
- 当 React 选择保留或重置状态时
- 如何强制 React 重置组件的状态
- 键和类型如何影响是否保留状态
状态绑定到渲染树中的位置
React 为 UI 中的组件结构构建渲染树。
当您给出组件状态时,您可能会认为该状态“存在于”组件内部。但状态实际上是在 React 内部保存的。React 通过该组件在渲染树中的位置将它所持有的每个状态片段与正确的组件相关联。
在这里,只有一个 JSX 标签,但它呈现在两个不同的位置:<Counter />
import { useState } from 'react'; export default function App() { const counter = <Counter />; return ( <div> {counter} {counter} </div> ); } function Counter() { const [score, setScore] = useState(0); const [hover, setHover] = useState(false); let className = 'counter'; if (hover) { className += ' hover'; } return ( <div className={className} onPointerEnter={() => setHover(true)} onPointerLeave={() => setHover(false)} > <h1>{score}</h1> <button onClick={() => setScore(score + 1)}> Add one </button> </div> ); }
下面是它们看起来像一棵树的样子:
反应树
这是两个独立的计数器,因为每个计数器都呈现在树中自己的位置。使用 React 通常不需要考虑这些位置,但了解它的工作原理会很有用。
在 React 中,屏幕上的每个组件都具有完全隔离的状态。例如,如果并排渲染两个组件,则每个组件都将获得自己的独立和状态。Counter
score
hover
尝试单击两个计数器,并注意它们不会相互影响:
import { useState } from 'react'; export default function App() { return ( <div> <Counter /> <Counter /> </div> ); } function Counter() { const [score, setScore] = useState(0); const [hover, setHover] = useState(false); let className = 'counter'; if (hover) { className += ' hover'; } return ( <div className={className} onPointerEnter={() => setHover(true)} onPointerLeave={() => setHover(false)} > <h1>{score}</h1> <button onClick={() => setScore(score + 1)}> Add one </button> </div> ); }
如您所见,当一个计数器更新时,仅更新该组件的状态:
更新状态
只要你在树中的同一位置渲染相同的组件,React 就会保持状态。要查看这一点,请递增两个计数器,然后通过取消选中“渲染第二个计数器”复选框来删除第二个组件,然后再次勾选它来重新添加它:
import { useState } from 'react'; export default function App() { const [showB, setShowB] = useState(true); return ( <div> <Counter /> {showB && <Counter />} <label> <input type="checkbox" checked={showB} onChange={e => { setShowB(e.target.checked) }} /> Render the second counter </label> </div> ); } function Counter() { const [score, setScore] = useState(0); const [hover, setHover] = useState(false); let className = 'counter'; if (hover) { className += ' hover'; } return ( <div className={className} onPointerEnter={() => setHover(true)} onPointerLeave={() => setHover(false)} > <h1>{score}</h1> <button onClick={() => setScore(score + 1)}> Add one </button> </div> ); }
请注意,当您停止渲染第二个计数器时,其状态将完全消失。这是因为当 React 删除一个组件时,它会破坏它的状态。
删除组件
当您勾选“渲染第二个计数器”时,第二个计数器及其状态将从头开始初始化 () 并添加到 DOM 中。Counter
score = 0
添加组件
React 会保留组件的状态,只要它在 UI 树中的位置被渲染。如果它被删除,或者不同的组件在同一位置被渲染,React 就会丢弃它的状态。