我们在 React 中使用 Javascript 中的 setTimeout 函数时遇到了一个奇怪的问题。
由于使用setTimeout内的代码,它的运行速度比不使用setTimeout的代码慢得多!

作为比较,性能结果为:

Using setTimeout: 1391 ms
without using setTimeout: 15 ms

在 API 回调中(例如 axios),setTimeout 版本也会发生!


简单的示例代码如下:
codesandbox

谁能解释一下发生了什么?

import React, { useState } from "react"; 
import ReactDOM from "react-dom"; 
 
function App() { 
  const [value, setValue] = useState(""); 
  const [time, setTime] = useState(""); 
 
  const startSample = () => { 
    const startTimeStamp = new Date().valueOf(); 
    for (let i = 0; i < 5000; i++) { 
      setValue(`test-${i}`); 
      // console.log(`test-${i}`); 
    } 
    const endTimeStamp = new Date().valueOf(); 
    setTime(`${endTimeStamp - startTimeStamp}ms`); 
  }; 
 
  const handleClick1 = () => { 
    startSample(); 
  }; 
 
  const handleClick2 = () => { 
    setTimeout(() => { 
      startSample(); 
    }); 
  }; 
 
  return ( 
    <div style={{ textAlign: "left" }}> 
      <p>{value || "Please push that button!"}</p> 
      <div> 
        <button id="startBtn" onClick={handleClick1}> 
          Start Normal 
        </button> 
        <button id="startBtn1" onClick={handleClick2}> 
          Start With setTimeout 
        </button> 
      </div> 
      <p>Result: {time}</p> 
    </div> 
  ); 
} 
 
const rootElement = document.getElementById("root"); 
ReactDOM.render(<App />, rootElement); 

请您参考如下方法:

React 批量渲染会在事件回调中排队,因此,一旦处理程序完成,您对点击处理程序中的 setValue 的所有调用都会导致一次渲染。

但是,我不相信 React 批处理会在 setTimeout 调用中进行渲染。因此,它会在每次调用 setTimeout 处理程序中的 setValue 后呈现。

查看此问题:https://github.com/facebook/react/issues/14259

您应该能够通过像这样编写 setTimeout 版本来更快:

const handleClick2 = () => { 
  setTimeout(() => ReactDOM.unstable_batchedUpdates(() => startSample())); 
} 

如果您有一堆异步 Ajax 响应返回,并希望在它们全部到达后应用它们,那么您可能有这样的代码:

const [a, setA] = useState(); 
const [b, setB] = useState(); 
const [c, setC] = useState(); 
const [d, setD] = useState(); 
 
useEffect(() => { 
  (async () => { 
    const a = await fetchA(); 
    const b = await fetchB(); 
    const c = await fetchC(); 
    const d = await fetchD(); 
 
    // wrap all of the state updates in batchUpdates 
    // so that we only get one render instead of 4 
    ReactDOM.unstable_batchUpdates(() => { 
      setA(a); 
      setB(b); 
      setC(c); 
      setD(d); 
    }); 
  })() 
}), []); 


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!