javascript 在react组件中检测第一次渲染的正确方法是什么

edqdpe6u  于 2023-05-16  发布在  Java
关注(0)|答案(5)|浏览(181)

我有一个场景,我需要检测组件的第一次渲染。在这里我建立了一个小例子。有人能告诉我什么是正确的方法吗?
为什么大多数人建议使用ref而不是普通状态?
https://codesandbox.io/s/condescending-burnell-0ex3x?file=/src/App.js

import React, { useState, useRef, useEffect } from "react";
import "./styles.css";

export default function App() {
  const firstRender = useDetectFirstRender();
  const [random, setRandom] = useState("123");
  useEffect(() => {
    if (firstRender) {
      console.log("first");
    } else {
      console.log("second");
    }
  }, [random]);
  return (
    <div className="App">
      <h1>Random Number is {random}</h1>
      <button onClick={() => setRandom(Math.random())}>Change Name</button>
    </div>
  );
}

//Approach 1
// export function useDetectFirstRender() {
//   const firstRender = useRef(true);

//   useEffect(() => {
//     firstRender.current = false;
//   }, []);

//   return firstRender.current;
// }

//Approach 2
export function useDetectFirstRender() {
  const [firstRender, setFirstRender] = useState(true);

  useEffect(() => {
    setFirstRender(false);
  }, []);

  return firstRender;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
jum4pzuy

jum4pzuy1#

您可以基于useRef创建一个可重用的custom hook

function useFirstRender() {
  const ref = useRef(true);
  const firstRender = ref.current;
  ref.current = false;
  return firstRender;
}
jrcvhitl

jrcvhitl2#

你可以使用useMemo或useCallback钩子来检测并保存它。但是这里最优选的是useMemo,因为它防止了一次又一次的相同渲染。

const firstRender = useMemo(
    () =>console.log('first Render'),
    []
  );

在这里,它将渲染一次并在第一次渲染中保存值,因此您可以在任何需要的地方使用它。

gcxthw6b

gcxthw6b3#

const firstRender = useRef(true);

useEffect(() => {
  if (firstRender.current) {
    firstRender.current = false;
    return;
  }
  doSomething();
});
vcudknz3

vcudknz34#

useEffect钩子接受第二个参数。第二个参数是一个变量数组,组件将检查这些变量,以确保它们在重新呈现之前已经更改。但是,如果该数组为空,则在初始呈现期间仅调用该钩子一次。这类似于之前发布的useMemo()技巧。

useEffect(() => doSomethingOnce(), [])
                                   ^^
b4wnujal

b4wnujal5#

当使用StrictMode时,做一些**useEffect()重置/清理**也很重要(return () => { isFirstRender.current = true };)。否则,isFirstRender.current将无法真正反映您想要的内容,从而导致意想不到的问题,尽管使用了[]依赖项,该依赖项假定仅在第一次渲染时运行(当组件被挂载时)。
如何在开发中处理两次发射的效果?:
React在开发过程中有意地重新装载组件,以找到像上一个例子中那样的bug。正确的问题不是“如何运行一次效果”,而是“如何修复我的效果,使其在重新安装后工作”。

const isFirstRender = useRef(true);

useEffect(() => {

  if (isFirstRender.current) {
    // Do something on first render...
  }

  isFirstRender.current = false;

  // ---> StrictMode: The following is REQUIRED to reset/cleanup:
  return () => { isFirstRender.current = true };

}, []); // ---> The `[]` is required, it won't work with `[myDependency]` etc.

相关问题