React基础 第十九章(State状态保留与重置)

在React应用开发中,理解何时以及如何保留或重置组件的状态是至关重要的。

理解React的状态保留机制

在React中,组件的状态(state)是与组件实例紧密关联的。React通过组件在UI树中的位置来决定是否保留状态。当组件在渲染过程中保持在UI树的同一位置时,React会保留其状态。这意味着,如果你在两次渲染之间没有改变组件的位置或没有改变生成组件的关键属性(如key),那么组件的状态将被保留。

当你在React应用中渲染组件时,React会根据组件的位置来决定是否应该保留其内部状态。如果组件在UI树中的位置没有改变,React会认为它是同一个组件实例,并保留其状态。

技巧

  • 为了保证组件状态不被重置,你需要确保在不需要重置状态时,组件在UI树中的位置保持不变。

示例

jsx 复制代码
function App() {
  // Counter组件在UI树的相同位置
  return (
    <div>
      <Counter />
      <Counter />
    </div>
  );
}

在例子中,我们有一个App组件,它渲染了两个Counter组件。由于这两个Counter组件在每次渲染时都处于UI树的相同位置,React将会保留它们的状态。

注意事项

  • 如果你决定移除一个组件,那么它的状态也会随之销毁。当组件从UI树中移除后,如果再次将其添加回来,它将是一个全新的组件实例,带有初始状态。

正确代码

jsx 复制代码
// 显示或隐藏第二个计数器,但不改变第一个计数器的状态
function App() {
  const [showSecondCounter, setShowSecondCounter] = useState(true);
  return (
    <div>
      <Counter />
      {showSecondCounter && <Counter />}
    </div>
  );
}

在这个例子中,我们通过一个布尔状态showSecondCounter来控制第二个Counter组件的显示与隐藏。当我们切换这个状态时,第一个Counter组件的状态不会受到影响,因为它的位置没有改变。

错误代码

jsx 复制代码
// 错误:每次App组件渲染时,Counter组件都会被重新创建,导致状态重置
function App() {
  return (
    <div>
      <Counter key={Date.now()} />
    </div>
  );
}

在错误示例中,每次App组件渲染时,都会给Counter组件一个基于当前时间的新key。这导致React认为它是一个全新的组件实例,并且每次都会重置它的状态。

强制重置组件状态

有时候,我们需要在组件保持在同一位置时重置其状态。

技巧

  • 使用不同的key属性来强制React重置组件状态。

示例

jsx 复制代码
function Scoreboard() {
  const [player, setPlayer] = useState('PlayerA');

  return (
    <div>
      {/* 通过改变key来重置Counter组件的状态 */}
      {player === 'PlayerA' ? <Counter key="PlayerA" /> : <Counter key="PlayerB" />}
      <button onClick={() => setPlayer(player === 'PlayerA' ? 'PlayerB' : 'PlayerA')}>
        切换玩家
      </button>
    </div>
  );
}

注意事项

  • key属性不是全局唯一的,只在其父组件中标识唯一性。

正确代码

jsx 复制代码
// 使用key属性来区分不同的Counter实例
<Counter key="PlayerA" />
<Counter key="PlayerB" />

错误代码

jsx 复制代码
// 错误:没有使用key属性,React会认为是同一个Counter实例
<Counter />
<Counter />

避免无意中重置状态

在某些情况下,我们可能无意中重置了组件的状态,这通常是由于不恰当的组件结构或key的使用。

技巧

  • 避免在组件内部定义其他组件,这可能会导致状态意外重置。

示例

jsx 复制代码
// 正确:将MyTextField定义在MyComponent外部
function MyTextField() {
  const [text, setText] = useState('');
  return <input value={text} onChange={e => setText(e.target.value)} />;
}

function MyComponent() {
  const [counter, setCounter] = useState(0);
  return (
    <>
      <MyTextField />
      <button onClick={() => setCounter(counter + 1)}>
        点击了{counter}次
      </button>
    </>
  );
}

注意事项

  • 确保组件定义在其使用的最外层作用域中。

正确代码

jsx 复制代码
// MyTextField定义在MyComponent外部,避免了状态重置
function MyTextField() { /* ... */ }
function MyComponent() { /* ... */ }

错误代码

jsx 复制代码
// 错误:MyTextField定义在MyComponent内部,每次渲染都会重置状态
function MyComponent() {
  function MyTextField() { /* ... */ }
  // ...
}

通过遵循这些技巧和注意事项,你可以更好地控制React组件的状态保留和重置,从而创建出更稳定和可预测的用户界面。记住,合理地使用key属性和组件位置是管理状态的关键。

相关推荐
我要洋人死1 小时前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai2 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9152 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼3 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
小牛itbull4 小时前
ReactPress:重塑内容管理的未来
react.js·github·reactpress