reactjs 显示useBetween呈现计数与计算的呈现计数不匹配

holgip5t  于 2022-11-22  发布在  React
关注(0)|答案(2)|浏览(102)

我有一个简单的响应工作示例,它显示了 “应用程序渲染器:2 ',但控制台日志只显示计算的渲染计数为1,但我不知道为什么。
通过日志查看钩子也不能告诉我渲染计数何时达到2,以及为什么渲染计数达到2。
下面链接指向codesandbox上的工作示例以及代码和控制台输出:
working example is also here

代码:

-应用程序. js-

import React, { useState, useCallback } from "react";
import { useBetween } from "use-between";

const useRenderCounts = () => {
  const [appRenderCnt, setAppRenderCnt] = useState(0);

  const bumpAppRenderCnt = () => {
    console.log(
      "bumpAppRenderCnt -> before setAppRenderCnt - appRenderCnt: ",
      appRenderCnt
    );
    setAppRenderCnt((prevRenderCnt) => {
      let newRenderCnt = prevRenderCnt + 1;
      console.log(
        "setAppRenderCnt old: ",
        prevRenderCnt,
        "new: ",
        newRenderCnt,
        "current appRenderCnt: ",
        appRenderCnt
      );
      return newRenderCnt;
    });
    console.log(
      "bumpAppRenderCnt -> after setAppRenderCnt - appRenderCnt: ",
      appRenderCnt
    );
  };

  return {
    appRenderCnt: appRenderCnt,
    bumpAppRenderCnt: bumpAppRenderCnt
  };
};

const useCounters = () => {
  const [sharedCnt, setSharedCnt] = useState(0);
  const incSharedCnt = useCallback(() => {
    setSharedCnt((sc) => sc + 1);
  }, []);
  const decSharedCnt = useCallback(() => {
    setSharedCnt((sc) => sc - 1);
  }, []);

  const [cnt1, setCnt1] = useState(0);
  const incCnt1 = useCallback(() => {
    setCnt1((c1) => c1 + 1);
    incSharedCnt();
  }, [incSharedCnt]);
  const decCnt1 = useCallback(() => {
    setCnt1((c1) => c1 - 1);
    decSharedCnt();
  }, [decSharedCnt]);

  const [cnt2, setCnt2] = useState(0);
  const incCnt2 = useCallback(() => {
    setCnt2((c2) => c2 + 1);
    incSharedCnt();
  }, [incSharedCnt]);
  const decCnt2 = useCallback(() => {
    setCnt2((c2) => c2 - 1);
    decSharedCnt();
  }, [decSharedCnt]);

  return {
    cnt1: cnt1,
    incCnt1: incCnt1,
    decCnt1: decCnt1,
    cnt2: cnt2,
    incCnt2: incCnt2,
    decCnt2: decCnt2,
    sharedCnt: sharedCnt
  };
};

const useSharedCounters = () => useBetween(useCounters);
const useSharedAppRenderCounters = () => useBetween(useRenderCounts);

const Renders = () => {
  const { appRenderCnt } = useSharedAppRenderCounters();
  return (
    <div>
      <p>App Renders: {appRenderCnt}</p>
    </div>
  );
};

const Counts = () => {
  const { cnt1, cnt2, sharedCnt } = useSharedCounters();
  return (
    <div>
      <p>Shared Count: {sharedCnt}</p>
      <p>Count 1: {cnt1}</p>
      <p>Count 2: {cnt2}</p>
    </div>
  );
};

const Buttons1 = () => {
  const { incCnt1, decCnt1 } = useSharedCounters();
  return (
    <>
      <button onClick={incCnt1}>+ Count 1</button>
      <button onClick={decCnt1}>- Count 1</button>
    </>
  );
};

const Buttons2 = () => {
  const { incCnt2, decCnt2 } = useSharedCounters();
  return (
    <>
      <button onClick={incCnt2}>+ Count 2</button>
      <button onClick={decCnt2}>- Count 2</button>
    </>
  );
};

const App = () => {
  const { appRenderCnt, bumpAppRenderCnt } = useSharedAppRenderCounters();
  console.log("App is rendering; before bump: ", appRenderCnt);

  bumpAppRenderCnt();

  console.log("App is rendering; after bump: ", appRenderCnt);

  return (
    <>
      <div>
        <Renders />
        <Counts />
      </div>
      <div>
        <h5>Buttons 1</h5>
        <Buttons1 />
      </div>
      <div>
        <h5>Buttons 2</h5>
        <Buttons2 />
      </div>
    </>
  );
};

export default App;

-索引. js-

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

控制台日志如下:

> App is rendering; before bump:  0
> bumpAppRenderCnt -> before setAppRenderCnt - appRenderCnt:  0
> setAppRenderCnt old:  0
> new:  1
> current appRenderCnt:  0
> bumpAppRenderCnt -> after setAppRenderCnt - appRenderCnt:  0
> App is rendering; after bump:  0
k4ymrczo

k4ymrczo1#

这个问题与<React.StrictMode>...</React.StrictMode>标记有关。或者,更一般地说,据我所知,React在严格模式/开发模式下进行了额外的渲染。
移除这些标记会将渲染计数减少为1,正如预期的那样。

mnemlml8

mnemlml82#

你好!
在React的StrictMode中重新调用Render是调试新并发模式的一种方法。这对于React 17和18也是不同的。https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects
要支持React 18的StrictMode,请使用useBetween版本1.3.4
大大的谢了!

相关问题