setTimeout 运行它的回调代码比没有它慢得多
setTimeout runs its callback codes much slower than without it
我们正在努力解决在 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);
});
})()
}), []);
React currently will batch state updates if they're triggered from
within a React-based event, like a button click or input change. It
will not batch updates if they're triggered outside of a React event
handler, like a setTimeout().
考虑以下因素
const startSample = () => {
const startTimeStamp = new Date().valueOf();
const arr = []
for (let i = 0; i < 5000; i++) {
arr.push(i)
// console.log(`test-${i}`);
}
setValue(arr)
const endTimeStamp = new Date().valueOf();
setTime(`${endTimeStamp - startTimeStamp}ms`);
};
现在这两个时间差不多了吧?正如 Brandon React 所指出的那样,似乎不会在触发新渲染之前等待所有更新完成,从而导致五千个渲染而不是一个。所以使用累加器来执行迭代并只设置一次状态
我们正在努力解决在 React Javascript 中使用 setTimeout
函数的一个奇怪问题。
由于使用 setTimeout
内的代码,它比 运行 没有 setTimeout
!
作为比较,性能结果为:
Using
setTimeout
: 1391 ms
without usingsetTimeout
: 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);
});
})()
}), []);
React currently will batch state updates if they're triggered from within a React-based event, like a button click or input change. It will not batch updates if they're triggered outside of a React event handler, like a setTimeout().
考虑以下因素
const startSample = () => {
const startTimeStamp = new Date().valueOf();
const arr = []
for (let i = 0; i < 5000; i++) {
arr.push(i)
// console.log(`test-${i}`);
}
setValue(arr)
const endTimeStamp = new Date().valueOf();
setTime(`${endTimeStamp - startTimeStamp}ms`);
};
现在这两个时间差不多了吧?正如 Brandon React 所指出的那样,似乎不会在触发新渲染之前等待所有更新完成,从而导致五千个渲染而不是一个。所以使用累加器来执行迭代并只设置一次状态