useMemo/useCallback 将来可能性のある隐患以上および実行可能な対策

10926 ワード

原因



この 2 つの API は安定していない可能性があり、将来的には関連する変更が必要になる可能性があります
具体的には、官方文档中のこの么一段话を見ることができます

You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.


続きを読む React コア チーム メンバー



もし未来の真上のこの機能が
  • は、現在のパッケージが内部保存されているかどうかをマークするために、追加の API を提供します.
  • 「メモ化を明らかに破る可能性がある」場所でのみ、「1 つのタブが隐藏了几分钟、解放掉仅仅されてメモ化されて占有されている可能性があります」

  • 社区已经有的代替案



    useMemoOne
    基本は用 useRef 再実装 useMemouseCallback
    useCreation
    ahooks の useMemo の代替品、または deps に応じて変更された useRef

    現在 useRef と useMemo useCallback 具体的な実装原理



    useRef

        function useRef<T>(initialValue: T): {|current: T|} {
          currentlyRenderingComponent = resolveCurrentlyRenderingComponent();
          workInProgressHook = createWorkInProgressHook();
          const previousRef = workInProgressHook.memoizedState;
          if (previousRef === null) {
            const ref = {current: initialValue};
            if (__DEV__) {
              Object.seal(ref);
            }
            workInProgressHook.memoizedState = ref;
            return ref;
          } else {
            return previousRef;
          }
        }
    


    useMemo

        function useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T {
          currentlyRenderingComponent = resolveCurrentlyRenderingComponent();
          workInProgressHook = createWorkInProgressHook();
    
          const nextDeps = deps === undefined ? null : deps;
    
          if (workInProgressHook !== null) {
            const prevState = workInProgressHook.memoizedState;
            if (prevState !== null) {
              if (nextDeps !== null) {
                const prevDeps = prevState[1];
                if (areHookInputsEqual(nextDeps, prevDeps)) {
                  return prevState[0];
                }
              }
            }
          }
    
          if (__DEV__) {
            isInHookUserCodeInDev = true;
          }
          const nextValue = nextCreate();
          if (__DEV__) {
            isInHookUserCodeInDev = false;
          }
          workInProgressHook.memoizedState = [nextValue, nextDeps];
          return nextValue;
        }
    


    useCallback

        export function useCallback<T>(
          callback: T,
          deps: Array<mixed> | void | null,
        ): T {
          return useMemo(() => callback, deps);
        }
    


    可见 useCallback 基本的には、() => fn に入る関数をより便利にするためであると言えます.

    相关料


  • この問題に関する详细の問題について 讨论: https://github.com/facebook/react/issues/15278
  • 比较流行的 one useMemo
  • React core team 成员在 Reddit 上的回复: https://github.com/alexreardon/use-memo-one
  • さまざまなフックの具体的な実装: https://www.reddit.com/r/reactjs/comments/mib8mr/usememo_docs_dont_reflect_how_it_is_used_in/gt6ouh8?utm_source=share&utm_medium=web2x&context=3

  • PS https://github.com/facebook/react/blob/cae635054e17a6f107a39d328649137b83f25972/packages/react-dom/src/server/ReactPartialRendererHooks.js 用的は React のトップレベル API MST observer 不用 useMemo