React.useMemo 与 React.useState

per*_*mon 1 javascript reactjs

我看到其他人询问useState + useEffect。但我想知道这两个实现中未更改(const)变量有什么不同:

function optionA(){
  const [Mesh]  = useState(()=> new Mesh)
  
 return "...someRender"
}

function optionB(){
 const Mesh = useMemo(()=> new Mesh)

 return "...someRender"
}
Run Code Online (Sandbox Code Playgroud)

编辑:

我知道useRef(someValue)更适合这一点,但我发现它“不声明”地写Mesh.current在任何地方

T.J*_*der 6

关键是你说的“不变”。拥有一个永远不会改变的状态值是没有意义的。状态的目的是保存信息,当这些信息发生变化时,将导致渲染更新。如果您从不更改它,则没有理由将其置于状态中。

\n

但是,不要用于useMemo此目的。从文档中:

\n
\n

您可以依赖 useMemo 作为性能优化,而不是作为语义保证。将来,React 可能会选择 \xe2\x80\x9c 忘记 \xe2\x80\x9d 一些以前记忆的值,并在下次渲染时重新计算它们,例如为屏幕外组件释放内存。编写代码,使其在没有useMemo\xe2\x80\x94 的情况下仍然可以工作,然后添加它以优化性能。

\n
\n

(他们的强调)

\n

如果您想要在组件的整个生命周期内静态保存信息,请使用useRef,而不是useMemo

\n
function Example() {\n    const refMesh = useRef(null);\n    if (!refMesh.current) {\n        // One-time initialization\n        refMesh.current = new Mesh();\n    }\n    const mesh = refMesh.current;\n    // ...use `mesh` from here on out...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

与 不同的是useMemo,您可以确定Mesh在组件的生命周期中仅创建一个实例。(这还有另一个微小的优点,即您不必不断创建一个函数来传递useMemo每个渲染。)

\n

我有时使用存储对象的单个引用来保存不适合状态的多条实例信息(包括子组件的稳定回调函数)。非常方便。

\n
\n

重新编辑:

\n
\n

我知道useRef(someValue)更适合这一点,但我发现它“不声明”地写Mesh.current在任何地方

\n
\n

你不知道。请参阅const mesh = refMesh.current;上面的内容,您将在组件的其余部分中使用mesh,而不是。refMesh.current

\n

如果您觉得if尴尬,您可以将其包装在一个钩子中,该钩子提供了未提供的语义保证useMemo,但代价是在每个渲染上创建一个函数(如useMemouseCallback等):

\n
const useData = (instanceInitializer) => {\n    const ref = useRef(null);\n    if (!ref.current) {\n        ref.current = instanceInitializer();\n    }\n    return ref.current;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

那么就会是:

\n
function Example() {\n    const mesh = useData(() => new Mesh());\n    // ...use `mesh` from here on out...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这在功能创建方面有(非常)轻微的额外成本,但具有更好的人体工程学效果。

\n