使用 Redux 在 React 中打印组件渲染编号

Print component render number in React with Redux

我有以下问题。我想打印一个与提供顺序相同的数字。为此,我创建了一个名为 title 的组件,用于打印 Redux 中数据的值。同样在同一个组件中,我使用了安全挂钩,它针对组件的每个表示执行。理论上,如果我的应用程序中有 6 次 title 组件,则将渲染 6 次,并执行 6 次。将被执行。按照这个逻辑,在安装中,我使用装运来设置我在组件上打印时的值。 reducing 函数只是一个 increase 函数,理论上,正确的行为必须是应用程序打印渲染组件的订单号。但他没有那样做,他所做的是在所有组件上打印一个固定的数字。这里代码代码:https://codesandbox.io/s/redux-call-api-eke2?file=/src/app.js

这里是代码:

应用组件

   import React from "react";
import "./App.css";
import Title from "./Title";

function App() {
  return (
    <div className="App">
      <div>
        <Title />
      </div>
      <div>
        <Title />
        <div>
          <Title />
        </div>
      </div>
      <div>
        <Title />
      </div>
      <Title />
      <Title />
      <Title />
      <Title />
      <Title />
    </div>
  );
}

export default App;

Slice Redux

import { createSlice } from "@reduxjs/toolkit";

export const slice = createSlice({
  name: "counter",
  initialState: {
    value: 0
  },
  reducers: {
    increment: (state) => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. Item
      // doesn't actually mutate the state because it uses the immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1;
    }
  }
});

export const { increment } = slice.actions;

export default slice.reducer;

标题组件

import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import {increment} from "./features/counter/counterSlice"

functionTitle() {
  const Counter = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  useEffect(() => {
    console.log("hi");
    dispatch(increment())
  }, []);

  return <h2>Render {Counter}</h2>;
}

export default Title;

虽然我还没有完全理解 real-world use-case。您可以通过以下方式完成此操作。

你不想为此使用 redux。状态(redux 或其他)的全部要点是保存应随时间变化的值,以及 re-render 在状态更新时使用它们的任何组件。因此,通过使用 Redux 来保存计数器,您将每个 Title 组件强制为 re-render 直到它们都使用最新值 (6).

相反,您可以使用常规变量,将其存储在 ref 中,然后在每次使用时递增它。

这个变量可以很容易地提取到它自己的文件中,以便在其他地方导入。

需要 useRef 以便我们在第一次渲染时只从 global_counter 读取一次。

let global_counter = 1;

function Title() {
  const local_counter = React.useRef(global_counter++);

  return <h2>Render {local_counter.current}</h2>;
}

function App() {
  return (
    <div>
      <div>
        <Title />
      </div>
      <div>
        <Title />
        <div>
          <Title />
        </div>
      </div>
      <div>
        <Title />
      </div>
      <Title />
      <Title />
      <Title />
      <Title />
      <Title />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

我想您甚至可以将其设为自定义挂钩,并稍微扩展逻辑以处理 re-renders 递增全局计数器;使其成为首选解决方案:

let global_counter = 1;

function useGlobalCounter() {
  const [count, setCount] = React.useState(() => global_counter++);
  
  return count;
}

function Title() {
  const local_counter = useGlobalCounter();
  const [state, setState] = React.useState(false);

  console.log(global_counter);
  return (
    <div>
      <h2>Render {local_counter}</h2>
      <button onClick={() => setState(!state)}>Re-render me</button>
    </div>
  );
}

function App() {
  return (
    <div>
      <Title />
      <Title />
      <Title />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

此解决方案更可靠,因为它以不递增 global_counter 的方式处理 re-render。它通过使用 useState 的函数初始值设定项来做到这一点,这样 global_counter++ 就不会在每次渲染时被评估——只有第一个。