我看到了关于useState + useEffect的其他问题。但是,我想知道在这两个实现中,对于未更改(const)变量有什么不同:
function optionA(){
const [Mesh] = useState(()=> new Mesh)
return "...someRender"
}
function optionB(){
const Mesh = useMemo(()=> new Mesh)
return "...someRender"
}编辑:
我知道useRef(someValue)更适合这样做,但我发现在任何地方编写Mesh.current都是“不声明性的”。
发布于 2022-04-09 12:51:38
关键是你说的“不变”。在状态中拥有一个永不改变的值是没有意义的。状态的目的是保存当更改时将导致呈现更新的信息。如果你不改变它,就没有理由让它进入状态。
但是,不要在这里使用useMemo。从文件中:
--您可能依赖useMemo作为性能优化,而不是作为语义保证。将来,可能会选择“忘记”一些以前回溯过的值,并在下次呈现时重新计算它们,例如释放屏幕外组件的内存。编写代码,使其在没有
useMemo的情况下仍然工作--然后添加它以优化性能。
(他们的重点)
如果您想在组件的整个生命周期中静态保存信息,请使用useRef,而不是useMemo。
function Example() {
const refMesh = useRef(null);
if (!refMesh.current) {
// One-time initialization
refMesh.current = new Mesh();
}
const mesh = refMesh.current;
// ...use `mesh` from here on out...
}与useMemo不同,您可以确定在组件的生命周期中只创建了一个Mesh实例。(这还具有另一个微小的优点,即您没有经常创建一个函数来在每次呈现时传递useMemo。)
有时,我使用存储一个对象的单个引用来保存不适合状态的多个实例信息(包括用于子组件的稳定回调函数)。挺方便的。
关于您的编辑:
我知道
useRef(someValue)更适合这样做,但我发现在任何地方编写Mesh.current都是“不声明性的”
没有,请参阅上面的const mesh = refMesh.current;,您将在整个组件的其余部分中使用mesh,而不是refMesh.current。
如果您发现if很尴尬,可以将其包装在一个钩子中,该钩子提供了useMemo没有提供的语义保证,代价是在每次呈现时创建一个函数(如useMemo、useCallback等):
const useData = (instanceInitializer) => {
const ref = useRef(null);
if (!ref.current) {
ref.current = instanceInitializer();
}
return ref.current;
};那就是:
function Example() {
const mesh = useData(() => new Mesh());
// ...use `mesh` from here on out...
}这有(非常)轻微的额外成本的功能创建,但更好的人机工程学。
https://stackoverflow.com/questions/71808192
复制相似问题