反应 SideEffect 脱离 useEffect 钩子

时间:2021-06-08 15:25:49

标签: javascript reactjs react-hooks use-effect

效果(增加 r 的值并记录它)在 useEffect 钩子中按预期工作

import React from "react";

let r = 0;

export default function App() {
  const [state, setState] = React.useState(false);

  function handler() {
    setState(!state);
  }

  React.useEffect(() => {
    r += 1;
    console.log("rendering:-", r, " times");
  });

  return (
    <>
      <button onClick={handler}>render</button>
    </>
  );
}

但是在 useEffect 钩子之外,效果意外地起作用。 r 的值增加 2 而不是 1

import React from "react";

let r = 0;
export default function App() {
  const [state, setState] = React.useState(false);

  function handler(params) {
    setState(!state);
  }

  r += 1;
  console.log("rendering:-", r, " times");

  return (
    <>
      <button onClick={handler}>render</button>
    </>
  );
}

但是为什么??? 有人可以解释我吗.....

2 个答案:

答案 0 :(得分:1)

实际上为 index.js 中的 strictMode rapper 调用了 2 次函数体

<React.StrictMode>
    <App />
</React.StrictMode>

根据React doc

<块引用>

严格模式无法自动为您检测副作用,但它可以 可以通过使它们更具确定性来帮助您发现它们。 这是通过有意重复调用以下函数来完成的:

答案 1 :(得分:0)

r 仍然增加 1,但是

<块引用>

注意:

从 React 17 开始,React 自动修改控制台 console.log() 之类的方法可以在第二次调用中使日志静音 生命周期函数。但是,它可能会导致不受欢迎的行为 可以使用变通方法的某些情况。

您可以在此处阅读更多相关信息:detecting-unexpected-side-effects

这是一个代码示例,显示 r 递增 1:

import React from "react";

let log = console.log
let r = 0;
export default function App() {
    const [state, setState] = React.useState(0);
    console.info('render');

    function handler(params) {
        setState((prevState) => prevState + 1);
    }

    r+=1;
    log("rendering:- r=" + r);
    log("rendering:- state=" + state);

    return (
        <>
            <button onClick={() => handler()}>render { state }</button>
        </>
    );
}