前提场景:代码中 buildProcessor 方法不能重复运行 ,useExecuter 方法只会用第一次结果
"use client";
import { useEffect, useMemo, useState } from "react";
export default function RenderTest() {
const [processor, setProcessor] = useState<number | undefined>();
// build processor
useEffect(() => {
const _processor = buildProcessor();
console.log("build processor", _processor.processor);
setProcessor(_processor.processor);
return () => {
console.log("cleanup processor", _processor.processor);
_processor.destroy();
};
}, []);
console.log("renderRenderTest, processor", processor);
//虽然该组件会被 react 强制执行两次,但是 ExecurerWrap 只会被渲染最后一次
return processor ? (
<ExecurerWrap processor={processor} />
) : (
<div>Loading...</div>
);
}
function ExecurerWrap({ processor }: { processor: number }) {
const executer = useExecuter(processor);
console.log("render ExecurerWrap, executer, processor", executer, processor);
return (
<div>
<div>渲染 executer:{executer}</div>
</div>
);
}
function buildProcessor() {
// 该函数构建了网络访问,因此不允许未销毁而重复创建
const seed = Date.now();
return {
processor: seed,
destroy: () => console.log("destory processor", seed),
};
}
/**
* 只会初始化一次,不会使用新的值
*/
function useExecuter(processor?: number) {
return useMemo(() => {
console.log("call processor", processor);
return processor;
}, []);
}
代码执行结果
page.tsx:33 renderRenderTest, processor undefined
page.tsx:8 mounted
page.tsx:25 build processor 1701061145592
page.tsx:15 unmounted
page.tsx:28 cleanup processor 1701061145592
page.tsx:58 destory processor 1701061145592
page.tsx:8 mounted
page.tsx:25 build processor 1701061145593
page.tsx:33 renderRenderTest, processor 1701061145593
page.tsx:67 call processor 1701061145593
page.tsx:67 call processor 1701061145593
page.tsx:45 render ExecurerWrap, executer, processor 1701061145593 1701061145593
以上我是构建了一个场景(我真实遇到的):useExecuter 方法由于会缓存第一次结果而不再更新,导致我无法在页面上渲染最新的 executer 。因此我采用包装了 ExecurerWrap ,实现按条件触发渲染。最终效果是成功了。
顺便对于 react 的严格模式我得到这样一个结论:它是把 hook 重新执行一次,而不是按着顺序把整个组件函数跑两遍,因此 build processor 构建了两次不一样的值,但是 ExecurerWrap 只有最后一次才真的被调用了。 (这个结论对吗)
最后也是最重要的 我上面这个解决 buildProcessor 方法不能重复运行和 useExecuter 方法只用第一次结果 的方案是不是合适的,有什么其他的方案吗?
————————
我这两天刚开始接触 react ,因此虚心求教大佬们。
