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 接收到新的引用地址,从而触发组件更新。
相关推荐
Violet_YSWY2 小时前
Vue import.meta.env 讲解
前端·javascript·vue.js
snow@li2 小时前
小程序-uniapp:vue3-typescript项目使用mp-html实现展示富文本
javascript·typescript·uni-app
暴富暴富暴富啦啦啦2 小时前
实现自定义指令 v-scrollBar,用于动态显示/隐藏滚动条,提升用户体验
前端·javascript·vue.js
_Kayo_2 小时前
css 练习笔记1
前端·css·笔记
weixin_440730502 小时前
css的选择器
前端·css·css3
消失的旧时光-19432 小时前
从前端路由到 Android ARouter:观察者模式在不同平台的同一种落地
android·前端·观察者模式·flutter
Shirley~~2 小时前
PPTist 画布工具栏
开发语言·前端·javascript
CDwenhuohuo2 小时前
移动端 刘海平上面顶部遮挡 解决
javascript
雨季~~2 小时前
前端使用ffmpeg进行视频格式转换 (WebM → MP4)
前端·typescript·ffmpeg·vue