精读React hook(一):useState 的几个基础用法和进阶技巧

自从 React v16.8 版本以来,React Hooks 为我们提供了全新的编写和思考 React 组件的方式。不仅管理状态和生命周期变得更简洁、更强大,Hooks 还引入了并发渲染和其他高级功能。本系列文章将详细探讨每一个 Hook,从基础到高级。首篇,我们将探讨最常用的 hook------useState。

useState 的基本用法

useState主要用于给组件添加状态变量。注意,我们只能在组件的顶层或自定义的 Hooks 中调用useState。

初始化状态

基础定义

tsx 复制代码
const [age, setAge] = useState(42);

懒初始化

对于需要计算得到的初始状态,可以使用函数传递给useState。这样,函数只在初次渲染时执行,而非每次渲染。

tsx 复制代码
const [todos, setTodos] = useState(createInitialTodos); // 注意:传递函数本身,非执行结果

更新状态

直接更新vs函数式更新

大部分情况,直接更新状态即可:

tsx 复制代码
setAge(newState);

但当新状态依赖于前一个状态时,推荐使用函数式更新。这确保了更新准确性,特别是在并发模式下。

tsx 复制代码
setState(prevState => prevState + 1);

以下两个例子展示函数式更新的重要性:

tsx 复制代码
// 示例1: 使用函数式更新
import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);

  function increment() {
    setAge(a => a + 1); // 函数式更新
  }

  return (
    <>
      <h1>Your age: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
    </>
  );
}
// 结果:点击 +3 时,age 更新为 45。
tsx 复制代码
// 示例2: 使用直接更新
import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);
  function increment() {
    setAge(age + 1); // 直接更新
  }
  return (
    <>
      <h1>Your age: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
    </>
  );
}
// 结果:点击 +3 时,可能只更新为 43。

对象与数组的更新

对象和数组的更新需要创建新的引用,而不是直接修改原状态。

tsx 复制代码
setForm({
  ...form,
  name: e.target.value // 更新这个属性
});

// 错误示例:
// form.name = e.target.value
tsx 复制代码
setTodos([
  ...todos,
  {
    id: nextId++,
    title: title,
    done: false
  }
]);

// 错误示例
// todos.push({
//   id: nextId++,
//   title: title,
//   done: false
// });
// setTodos(todos);

函数的更新

把函数存储到state里是很少见的做法,但某些情况下,我们有可能需要这么做。

先看一个错误的示例:

tsx 复制代码
const [fn, setFn] = useState(someFunction);

function handleClick() {
  setFn(someOtherFunction);
}

根据上文,我们知道这样的用法是把函数的返回值存储或更新到状态中,并不是把函数存储到状态中。

如果你想在状态中存储一个函数,你需要使用一个箭头函数来"包裹"它。这是正确的做法:

tsx 复制代码
const [fn, setFn] = useState(() => someFunction);

function handleClick() {
  setFn(() => someOtherFunction);
}

那么我们什么时候会需要这样使用?这里介绍一些可能的场景:

  1. 可配置的行为: 你可能有一个组件,它的行为可以由父组件进行配置。在这种情况下,你可以将函数作为状态存储,以便在组件的生命周期中更改或更新它。
  2. 动态创建的函数: 在某些情况下,你可能需要基于组件的某些属性或状态动态创建函数。将这些函数存储为状态可以确保你只在必要时重新创建它们。
  3. 回调和外部交互: 如果你的组件与外部系统交互,并且需要提供回调函数,你可能希望在状态中存储这些回调函数,以便在适当的时候更改或更新它们。
  4. 延迟执行的函数 : 在某些情况下,你可能想要在将来的某个时间点执行函数(例如,使用setTimeout)。将函数存储为状态可以确保即使组件的其他部分发生变化,你也可以访问到最初的函数引用。
  5. 与第三方库的集成: 有些第三方库可能要求你提供并在后续更改函数。在这种情况下,将函数作为状态存储可能会更加方便。

结语

在这篇文章中,我们深入探讨了 React 的useStateHook,从它的基础用法到一些进阶技巧。掌握好useState是走向 React 高手之路的关键一步。在未来的文章中,我们还将继续探讨其他的 Hooks。

相关推荐
java1234_小锋2 小时前
【技术专题】HTML5 网页技术 - HTML5 Canvas 基础以及动画入门
前端·html·html5
知了学历孙老师5 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
ShineWinsu7 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说8 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
志尊宝9 小时前
AI原生前端开发(009):AI辅助性能分析与优化建议
人工智能·react.js·ai-native
程序员老赵10 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot10 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot10 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
狒狒AI10 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc
修炼的dance10 小时前
浏览器里导出H.265,8.5秒和55.5秒差在硬件
前端