结论:
16 hooks版本
默认render1次
同步中,无论多少种类还是次数,都render 1次。
异步中,无论多少种类还是次数,1个种类执行1次,多次的话,用n*2。
18 hooks版本
默认render2次,
同步中,无论多少种类还是次数,都render 2次。
异步中,无论多少种类还是次数,都render 2次。
15版本, class版本
this.setState是异步的,set 3次就会合并,在callback可以获取最新值
但是在setTimeout同步的。(set 3次就会执行三次)
15 class版本看这个地址
react18
js
import React, { useState, useEffect } from 'react';
// 最新的react 16
function Test() {
console.log('----render') // 默认执行2次
const [countA, setCountA] = useState(111);
const [countB, setCountB] = useState(222);
function onClick() {
// 一个种类,一个set执行2次render
// 二个种类,各一次set,那么执行2次render
// 二个种类及以上,执行2次render,还是执行2次
setCountA(countA + 1)
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
setTimeout(() => {
// 一个种类,一个set执行2次render
// 二个种类,各一次set,那么执行2次render
// 二个种类及以上,执行2次render,还是执行2次
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
});
}
useEffect(() => {
}, []);
return (
<div>
<p>{countA}-{countB}</p>
<button onClick={onClick}>点击我</button>
</div>
)
}
export default Test;
react16
js
import React, { useState, useEffect } from 'react';
// 最新的react 16
function Test() {
console.log('--render') // 默认执行1次
const [countA, setCountA] = useState(111);
const [countB, setCountB] = useState(222);
function onClick() {
// 一个种类,一个set执行1次render
// 二个种类,各一次set,那么执行1次render
// 二个种类及以上,执行2次render,还是执行1次
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountA(countA + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
// setCountB(countB + 1)
setTimeout(() => {
// 一个种类,一个set执行1次render
// 二个种类,各一次set,那么执行2次render
// 二个种类及以上n,执行2次render及以上,n*2
setCountA(countA + 1)
setCountA(countA + 1)
setCountA(countA + 1)
setCountA(countA + 1)
setCountB(countB + 1)
setCountB(countB + 1)
setCountB(countB + 1)
setCountB(countB + 1)
});
}
useEffect(() => {
}, []);
return (
<div>
<p>{countA}-{countB}</p>
<button onClick={onClick}>点击我</button>
</div>
)
}
export default Test;
react16, 18
js
import React, { useState } from 'react';
function App() {
const [number, setNumber] = useState(0);
function alertNumber() {
setTimeout(() => {
alert(number); // 操作步骤,先点击弹窗,然后快速+按钮,永远弹出的是0,16和18都这样子
}, 3000);
}
return (
<div className="App">
<p>{number}</p>
<button onClick={() => setNumber(number + 1)}>+</button>
<button onClick={alertNumber}>alertNumber</button>
</div>
);
}
export default App;
一下的以前的博客,不可靠
react刷新几次问题
15版本, class版本
this.setState是异步的,set 3次就会合并,在callback可以获取最新值
但是在setTimeout同步的。(set 3次就会执行三次)
15 class版本看这个地址16版本,hooks版本
setState set几次就会render几次,但是有惰性。不会批处理。
18版本
批处理了。异步。可以调用同步的api。
setTimeout中的也可以批处理了。
legacy模式下:命中batchedUpdates时是异步 未命中batchedUpdates时是同步的
concurrent模式下:都是异步的,react 17添加了这个concurrent模式
react 16 setTimeout异步中的setA不可控制
useState会对state进行逐个处理,useState的原理是用闭包机制,而setTimeout中任务是无法拿到闭包中的变量的,所以,当遇到 setTimeout时,在setTimeout拿不到最新的值。
setState会进行一个合对象的,则只会处理最后一次。
当遇到 setTimeout/setInterval/Promise.then(fn)/fetch 回调/xhr 网络回调时,react 都是无法控制的,这个根react本身的原因有关系。
react 18 中对setTimeout中连续两次的setA也进行了合并,不知道18中setTimeout可不可以控制。
clike
const [a, setA] = useState(123);
console.log('----render');
return (
<div className="App">
<h1>{a}</h1>
<button onClick={() => {
// react 16 刷新两次, 结果仍然为124 react18刷新一次
setA(a+1);
setA(a+1);
}}>fffff</button>
</div>
);
----------------------------------------
const [number,setNumber] = useState(0);
function alertNumber(){
setTimeout(()=>{
alert(number); // 不论您点击多少次下边的click这里就是0
},3000);
}
return (
<>
<p>{number}</p>
<button onClick={()=>setNumber(number+1)}>+</button>
<button onClick={alertNumber}>alertNumber</button>
</>
)
----------------------------------------
export default function App() {
console.log('render----');
const [ca, setCa] = useState(1);
const aclick = () => {
setTimeout(() => {
// 会执行两次,但是最后的结果只会+1
setCa(ca + 1);
setCa(ca + 1);
});
}
return (
<div className="App" onClick={aclick}>
{ca}
</div>
);
}