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 接收到新的引用地址,从而触发组件更新。
相关推荐
毕设源码-赖学姐1 分钟前
【开题答辩全过程】以 基于WEB的实验室开放式管理系统的设计与实现为例,包含答辩的问题和答案
前端
幻云20104 分钟前
Python深度学习:从筑基到登仙
前端·javascript·vue.js·人工智能·python
我即将远走丶或许也能高飞2 小时前
vuex 和 pinia 的学习使用
开发语言·前端·javascript
钟离墨笺2 小时前
Go语言--2go基础-->基本数据类型
开发语言·前端·后端·golang
爱吃泡芙的小白白2 小时前
Vue 3 核心原理与实战:从响应式到企业级应用
前端·javascript·vue.js
卓怡学长3 小时前
m115乐购游戏商城系统
java·前端·数据库·spring boot·spring·游戏
码上成长3 小时前
JavaScript 数组合并性能优化:扩展运算符 vs concat vs 循环 push
开发语言·javascript·ecmascript
老陈聊架构3 小时前
『AI辅助Skill』掌握三大AI设计Skill:前端独立完成产品设计全流程
前端·人工智能·claude·skill
油丶酸萝卜别吃4 小时前
Mapbox GL JS 表达式 (expression) 条件样式设置 完全指南
开发语言·javascript·ecmascript
Ulyanov4 小时前
从桌面到云端:构建Web三维战场指挥系统
开发语言·前端·python·tkinter·pyvista·gui开发