React组件中useMemo回调多次触发问题及单次调用方案问询
问题解析与解决方案
为什么updateLogAndGetId被调用4次?
这是因为**React开发环境的严格模式(Strict Mode)**会刻意重复调用useMemo这类钩子的回调函数,目的是检测代码中潜在的非纯函数副作用。
你的代码里渲染了两个MyComponent实例,在严格模式下,每个实例的useMemo回调会被执行两次:第一次是正常渲染,第二次是React用来验证重复执行是否会引发问题的校验逻辑。两个实例各执行两次,最终就出现了4次调用。
至于HTML显示1和3,是因为useMemo会复用第一次执行的缓存结果,第二次执行的返回值会被忽略。但你的全局id变量每次调用都会自增,所以第一个组件第一次调用返回0、第二次返回1,最终组件使用的是缓存的1;第二个组件第一次返回2、第二次返回3,最终使用的是缓存的3,因此DOM呈现这两个值。
如何确保每个组件仅调用一次updateLogAndGetId?
方案1:利用useRef存储唯一ID
useRef的.current属性不会随组件重渲染重置,初始化逻辑只会执行一次,不受严格模式重复渲染的影响:
import { useRef } from "react"; let id = 0; export const MyComponent = () => { const componentIdRef = useRef(null); if (!componentIdRef.current) { componentIdRef.current = ++id; console.log(componentIdRef.current); } const componentId = componentIdRef.current; console.log("outside", componentId); return <li>{componentId}</li>; };
方案2:生产环境自动消除重复调用
严格模式的重复调用逻辑仅存在于开发环境,生产环境打包后,React会自动关闭该校验,每个组件的useMemo回调只会执行一次。
方案3:改用纯函数式ID生成(可选)
如果场景允许,可使用纯函数生成唯一ID(比如结合组件的props或上下文),避免依赖全局变量。但如果必须生成实例唯一ID,useRef的方案更直接可靠。
内容的提问来源于stack exchange,提问作者Tau
相关产品推荐
相关产品推荐

