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

React.useMemo与React.useState差异探究:不变常量变量的两种实现对比及useRef使用困惑

Differences Between useState and useMemo for Persistent Constants in React

Great question! Let's break down the key differences between these two approaches, especially since you're aware useRef is the intended tool but prefer a more declarative syntax without .current.

First, let's clarify a critical detail in your provided code:

Your Option B uses useMemo without a dependency array. This means the callback () => new Mesh will run every single time the component re-renders, creating a new Mesh instance on each render. That's almost certainly not what you want for an "unchanging constant." So I'll cover two scenarios for Option B: as-written, and with an empty dependency array (useMemo(() => new Mesh, [])) which aligns with your goal of one-time initialization.


1. Core Behavior & Instance Persistence

Option A: useState(() => new Mesh)

  • The initialization callback (() => new Mesh) runs only once: on the component's first render. React stores the resulting Mesh instance as state, and reuses it for all subsequent renders (even if the component re-renders multiple times).
  • In React Strict Mode (development environment), the callback runs twice, but React discards the first instance and keeps the second—so you still end up with a single persistent instance after the initial render cycle.

Option B (as-written: no dependency array)

  • The useMemo callback runs on every render, creating a new Mesh instance each time. This completely defeats the purpose of an "unchanging constant"—you'll get a new instance every time your component re-renders (e.g., when props or state change).

Option B (with empty dependency array: useMemo(() => new Mesh, []))

  • The callback runs only once (first render, plus twice in Strict Mode like useState), and the Mesh instance is cached for all subsequent renders. In terms of instance persistence, this behaves almost identically to Option A.

2. Semantic Intention & Code Clarity

This is where the biggest practical difference lies:

  • Option A: useState is designed for managing mutable state (values you expect to update with a setter function). By using it to store an unchanging constant, you're misusing its intended purpose. Other developers reading your code will wonder: "Why is this a state variable if it never changes? Should I be updating it somewhere?" It creates unnecessary confusion.
  • Option B (with empty dependencies): useMemo is intended for caching expensive computation results. While creating a Mesh instance might not be "expensive," using useMemo at least signals that you want to avoid recreating the value on every render. This is more semantically appropriate than useState, but still not the perfect fit for a persistent constant that doesn't depend on any inputs.
  • useRef (your alternative): It's explicitly designed for persisting values across renders without triggering re-renders, which is exactly your use case. The .current syntax might feel clunky, but it's a clear signal to other developers that this is a persistent reference, not state or a cached computation.

3. Edge Cases & Cleanup

  • Neither useState nor useMemo provides built-in cleanup for the Mesh instance. If your Mesh requires cleanup (e.g., releasing resources when the component unmounts), you'll need to pair either approach with a useEffect hook:
    useEffect(() => {
      return () => {
        // Clean up Mesh instance here
        Mesh.destroy();
      };
    }, [Mesh]);
    
    With useRef, this would look similar but use Mesh.current instead.

A Better Middle Ground (If You Hate .current)

Since you find useRef's syntax unappealing, you can wrap it in a custom Hook to get a declarative, .current-free experience:

function useConstant(initializer) {
  const ref = useRef();
  // Initialize only once
  if (!ref.current) {
    ref.current = initializer();
  }
  return ref.current;
}

// Usage in your component
function MyComponent() {
  const Mesh = useConstant(() => new Mesh);
  // Use Mesh directly, no .current needed!
  return "...someRender";
}

This custom Hook gives you the persistence of useRef with the clean, declarative syntax you want—plus it's semantically clear to other developers that this is an unchanging constant.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:07:45