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>
  );
}
相关推荐
爱分享的鱼鱼15 分钟前
对比理解 Vue 响应式 API:data(), ref、reactive、computed 与 watch 详解
前端·vue.js
JS_GGbond16 分钟前
【性能优化】给Vue应用“瘦身”:让你的网页快如闪电的烹饪秘籍
前端·vue.js
T___T18 分钟前
一个定时器,理清 JavaScript 里的 this
前端·javascript·面试
代码小学僧19 分钟前
从 Arco Table 迁移到 VTable:VTable使用经验分享
前端·react.js·开源
微笑的曙光20 分钟前
Vue3 环境搭建 5 步走(零基础友好)
前端
不知名用户来了24 分钟前
基于vue3 封装的antdv/element-Plus 快速生成增删改查页面
前端
明川30 分钟前
Android Gradle - ASM + AsmClassVisitorFactory插桩使用
android·前端·gradle
San3030 分钟前
深度驱动:React Hooks 核心之 `useState` 与 `useEffect` 实战详解
javascript·react.js·响应式编程
布列瑟农的星空31 分钟前
webpack迁移rsbuild——配置深度对比
前端
前端小黑屋32 分钟前
查看项目中无引用到的文件、函数
前端