You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何组件重渲染时useState初始值函数getSth会重复调用?

React组件重渲染时useState初始值函数重复调用问题解答

问题

点击按钮修改isSth状态导致组件重渲染时,明明未改变randomValue状态,函数getSth(可通过console.log观测到)为何每次都会被调用?

示例代码1

import React, { useState } from 'react';

function getSth() {
  console.log('init');
  return Math.random();
}

function Home() {
  const [randomValue, setRandomValue] = useState(getSth());
  const [isSth, setIsSth] = useState(false);

  console.log(randomValue);

  const onClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setIsSth((prev) => !prev);
  };

  return (
    <button type="button" onClick={onClick}>
      Click me
    </button>
  );
}

export default Home;

而采用如下写法时,getSth仅被调用一次?

示例代码2

const [randomValue, setRandomValue] = useState(0);
useEffect(() => {
  getSth();
}, []);

原因解析

示例1中getSth重复执行的本质

React组件每次重渲染时,整个组件函数都会从头到尾重新执行一遍。你在useState里写的是useState(getSth()),这意味着组件每次执行时,都会先调用getSth()得到返回值,再把这个值传给useState。

虽然useState内部会记住第一次的初始值,后续重渲染时不会更新randomValue,但getSth()的调用是在useState执行前就发生的——组件每渲染一次,这个函数调用就会触发一次,所以你能看到console.log('init')每次都输出。

换个直白的说法:useState(getSth())等价于先执行const temp = getSth(),再执行useState(temp),组件重渲染时这个temp的赋值步骤会重复执行。

示例2中getSth仅执行一次的原因

useEffect的第二个参数是依赖数组,当传入空数组[]时,这个useEffect只会在组件首次挂载完成后执行一次。后续组件重渲染时,因为依赖数组没有任何变化,React不会再触发这个useEffect,所以里面的getSth只会被调用一次。

更优的写法:useState惰性初始值

如果你的需求是让getSth只作为useState的初始值执行一次,其实不用useEffect,直接把getSth作为函数传给useState即可:

const [randomValue, setRandomValue] = useState(getSth);

这种写法下,React只会在组件首次渲染时调用getSth获取初始值,后续重渲染时不会再执行该函数,这是React官方推荐的惰性初始值用法,专门用来处理初始值计算开销较大的场景。

内容的提问来源于stack exchange,提问作者Unlucky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:46:09