React Hooks-即使状态未更改,也会触发useEffect

Enr*_*ent 4 reactjs react-hooks

我在组件内部设置了一个效果,如果另一个状态属性发生更改,该效果也会更改视图。但是由于某种原因,即使安装了该组件,该组件的效果仍会运行,即使的值detailIndex没有更改。

const EventsSearchList = () => {
    const [view, setView] = useState('table');
    const [detailIndex, setDetailIndex] = useState(null);

    useEffect(() => {
        console.log('onMount', detailIndex);
        // On mount shows "null"
    }, []);


    useEffect(
        a => {
            console.log('Running effect', detailIndex);
            // On mount shows "null"!! Should not have run...
            setView('detail');
        },
        [detailIndex]
    );

    return <div>123</div>;

};
Run Code Online (Sandbox Code Playgroud)

为什么会这样呢?

更新:如果不清楚,我正在尝试的是在组件更新时运行效果,因为detailIndex更改了。挂载时不行。

Bar*_*wen 8

就我而言,即使我在 useEffect() 中使用了第二个参数,组件也会不断更新,并且我正在打印该参数以确保它没有改变,也没有改变。问题是我正在使用 map() 渲染组件,并且在某些情况下键发生了变化,如果键发生了变化,对于 react 来说,它是一个完全不同的对象。

  • 这个答案非常有用! (4认同)

vsy*_*ync 7

确保代码useEffect仅在依赖项发生更改时运行,而不是在初始安装(第一次渲染)时运行的一种方法是分配一个最初false且仅true 在第一次渲染后才变为的变量,并且该变量自然应该是一个hook,因此它将在组件的整个生命周期内被记住。

\n

3种不同的比较useEffect

\n

\r\n
\r\n
const {useEffect, useRef, useState} = React\n\nconst App = () => {\n  const mountedRef = useRef()                 // \xe2\x86\x90 the "flag"\n  const [value, setValue] = useState(false)   // simulate a state change \n  \n\n  // with the trick\n  useEffect(() => {\n      if (mountedRef.current){                // \xe2\x86\x90 the trick\n          console.log("trick: changed")\n      }\n  }, [value])\n\n\n  // without the trick\n  useEffect(() => {\n     console.log("regular: changed")\n  }, [value])\n\n\n  // fires once & sets "mountedRef" ref to "true"\n  useEffect(() => {\n    console.log("rendered")\n    mountedRef.current = true\n    // update the state after some time\n    setTimeout(setValue, 1000, true)\n  }, [])\n    \n  return null\n}\n\nReactDOM.render(<App/>, document.getElementById("root"))
Run Code Online (Sandbox Code Playgroud)\r\n
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>\n<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>\n<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n


far*_*ard 6

useEffect默认情况下,React Hooks中的from from Hooks在每个渲染上执行,但是您可以在函数中使用第二个参数来定义何时再次执行效果。这意味着该功能始终在安装时执行。根据您的情况,第二个useEffect将在启动时以及detailIndex更改时运行。

更多信息:https//reactjs.org/docs/hooks-effect.html

资源:

有经验的JavaScript开发人员可能会注意到,传递给useEffect的函数在每个渲染器上都会有所不同。[...]如果在重新渲染之间某些值未更改,您可以告诉React跳过应用效果。为此,请将数组作为可选的第二个参数传递给useEffect:[...]

  • 还值得注意的是,“useEffect”中的函数是在渲染之后运行的,而不是渲染之前。很容易忘记,因为这些定义通常位于功能组件定义的顶部。 (4认同)

Dan*_*nex 5

您可以添加第二个守卫,检查 detailIndex 是否已从初始值更改为 -1

 useEffect(
    a => {
     if(detailIndex != -1)
      {  console.log('Running effect', detailIndex);
        // On mount shows "null"!! Should not have run...
        setView('detail');
    }},
    [detailIndex]);
Run Code Online (Sandbox Code Playgroud)

  • 守卫是做到这一点的唯一方法吗?对于像 React 这样的框架来说,它看起来太老套了 (2认同)