【问题标题】:How many time React should render?React 应该渲染多少次?
【发布时间】:2021-11-24 20:30:03
【问题描述】:

我写了一个简单的 React 来测试 React 是如何渲染的

import ReactDOM from 'react-dom';
import React, { useState, useEffect } from 'react';

const App = (props) => {
  // State
  const [trackIndex, setTrackIndex] = useState(1);
  const [trackProgress, setTrackProgress] = useState(0);
  const clickHandler = () =>{
       setTrackIndex((trackIndex)=>trackIndex+1)
  }

  useEffect(() => {
    console.log("effect; trackIndex=",trackIndex)
    console.log("effect; trackProgress=",trackProgress)
    if(trackIndex<5){
      console.log("set trackProgress")
      setTrackProgress(trackIndex)
    }
  });

  console.log("render")

  return (
    <div>
      <p>{trackIndex}</p>
      <p>{trackProgress}</p>
      <button onClick={clickHandler}>Click me</button>
    </div>
  );
};

ReactDOM.render(
  <App />,
document.getElementById('root')
);

以下是控制台输出:

render
effect; trackIndex= 1
effect; trackProgress= 0
set trackProgress
render
effect; trackIndex= 1
effect; trackProgress= 1
set trackProgress
render

在我单击按钮之前,React 似乎渲染了三次。最后的渲染真的让我很困惑。谁能向我解释为什么会发生这种渲染以及为什么渲染后没有效果?提前谢谢你

【问题讨论】:

    标签: javascript reactjs rendering


    【解决方案1】:

    您的useEffect 似乎在组件的初始渲染上使用setTrackProgress 设置状态。这是因为trackIndex 从小于5 的1 开始。(由if(trackIndex&lt;5) 看到)请注意,您没有将数组依赖项提供给useEffect 作为第二个参数。根据react-documentation,这意味着效果只会在组件第一次初始渲染后出现一次。

    另外,我建议将useCallback 添加到您的clickHandler 中,以防止为每个渲染重新定义函数。 (根据react-documentation

    【讨论】:

      【解决方案2】:

      您实际上是在进行无限循环,但 React 可以拯救您。第一个render 日志是初始渲染,然后useEffect 被执行并且你的组件重新渲染,导致第二个render 日志和第一个effect; ... 日志。现在执行第二个useEffect。但是,trackIndex 的值没有改变,因此您的 if 语句将评估 true 并使用相同的状态/值 (1) 更新 trackProgress。这导致另一个重新渲染和第三个render 日志。现在,你会认为第三个 useEffect 会被执行,但 React 足够聪明,可以知道状态何时没有改变,因此不会执行 useEffect

      如上所述,将依赖项添加到您的useEffect。这会解决你的问题。

      useEffect(
        ...
      , [trackIndex])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-15
        • 2022-07-04
        • 2020-05-20
        • 1970-01-01
        • 2023-02-13
        相关资源
        最近更新 更多