React中的useState传入函数的好处

目录

用法解释

[1. useState(getArr) vs useState(getArr())](#1. useState(getArr) vs useState(getArr()))

[2. 数组的不可变更新](#2. 数组的不可变更新)


说明

代码示例

javascript 复制代码
import React, { FC, useState } from 'react'

/**
 * 模拟一个昂贵的计算函数
 * 
 * 这个函数的作用是创建并填充一个长度为 100 的数组。
 * 我们在函数内部打印日志,是为了观察它被调用的时机。
 */
function getArr() {
  // 只有当 getArr 被执行时,控制台才会打印 'getArr...'
  // 这帮助我们理解 useState 传参的执行机制
  console.log('getArr...')

  // 创建一个长度为 100 的空数组
  const arr = new Array(100)
  
  // 将数组的每一个元素填充为字符串 'hello'
  arr.fill('hello')
  
  // 返回填充好的数组
  return arr
}

/**
 * React 函数组件 Demo
 * 
 * 该组件演示了:
 * 1. useState 的惰性初始化(传入函数)
 * 2. 不可变数据更新(展开运算符)
 */
const Demo: FC = () => {
  // 每次组件渲染(重新执行)时,都会打印 'demo...'
  console.log('demo...')

  // --- 状态定义 ---
  // useState 接收一个函数 getArr 作为参数。
  // 这是"惰性初始化"的写法。
  // React 会执行 getArr(),将其返回值作为 arr 的初始值。
  // 关键点:getArr 只会在组件的**首次渲染**时执行,后续重新渲染组件时,该函数不会再次执行。
  const [arr, setArr] = useState(getArr)

  // --- 事件处理函数 ---
  // 点击按钮时触发
  function addStr() {
    // 1. 使用展开运算符 (...) 复制原数组 arr 的所有元素
    // 2. 在新数组末尾添加一个新元素 'hello'
    // 3. 使用 setArr 更新状态
    // 注意:不能直接修改原数组 arr.push(),必须返回一个新数组来触发视图更新
    setArr([...arr, 'hello'])
  }

  // --- JSX 渲染结构 ---
  return (
    <>
      {/* 显示当前数组的长度 */}
      <p>length: {arr.length}</p>
      
      {/* 包含操作按钮的容器 */}
      <div>
        {/* 点击按钮调用 addStr 函数 */}
        <button onClick={addStr}>add</button>
      </div>
    </>
  )
}

export default Demo

结果:getArr函数,只在初始化的时候,执行一次

用法解释
1. useState(getArr) vs useState(getArr())

代码中使用的是 useState(getArr)(传入函数引用),而不是 useState(getArr())(传入函数执行结果)。

  • useState(getArr) (当前代码):
    • 机制: 惰性初始化。getArr 函数只会在组件第一次渲染 时执行一次,用来计算初始 state。之后即使组件因为状态更新而重新渲染,getArr 也不会再执行。
    • 适用场景: 当初始 state 需要通过昂贵的计算(如创建大数组、复杂计算)才能获得时,使用这种方式可以优化性能。
  • useState(getArr()):
    • 机制: 每次组件渲染(重新执行)时,都会先执行 getArr() 函数,然后将结果传给 useState。这会导致不必要的重复计算。
2. 数组的不可变更新

addStr 函数中,使用了 [...arr, 'hello']

  • 原因: React 中的状态(State)是不可变的。如果你直接使用 arr.push('hello') 修改原数组,数组的引用地址没有变,React 会认为状态没有变化,从而不会触发视图重新渲染
  • 解决: 使用展开运算符 ... 创建一个新数组,setArr 接收到新的引用地址,从而触发组件更新。
相关推荐
IT_陈寒40 分钟前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰1 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
山河木马2 小时前
渲染管线-计算得到gl_Position(顶点着色器)之后续GPU流程
javascript·webgl·图形学
竹林8182 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花2 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12273 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪3 小时前
Vue3-生命周期
前端
莪_幻尘4 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4534 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端
林瞅瞅4 小时前
Nuxt3 项目部署 Nginx 防盗链后特定 JS 文件 403 问题修复方案
前端