react151618刷新几次的问题

结论:

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>
  );
}
相关推荐
小小愿望几秒前
前端读取与导出XLSX文件实战指南(React+Ant Design)
前端
小小愿望10 分钟前
JavaScript生成随机数的全面指南:别再只会用Math.random()了!
前端
Jackson__17 分钟前
RAG究竟是什么?一文搞懂大模型的记忆增强术
前端
雲墨款哥19 分钟前
JS算法练习-Day10-判断单调数列
前端·javascript·算法
前端市界19 分钟前
前端视角: PyQt6+Vue3 跨界开发实战
前端·qt·pyqt
阅文作家助手开发团队_山神21 分钟前
第四章:Flutter自定义Engine本地依赖与打包流程
前端·flutter
JuneXcy24 分钟前
11.web api 2
前端·javascript·html
zYear30 分钟前
Elpis 全栈应用框架-- 总结
前端·javascript
Juchecar1 小时前
分析:将现代开源浏览器的JavaScript引擎更换为Python的可行性与操作
前端·javascript·python
极客小俊1 小时前
Font Awesome 一个基于CSS和LESS的免费图标库工具包
前端