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>
  );
}
相关推荐
掘金安东尼1 天前
让 JavaScript 更容易「善后」的新能力
前端·javascript·面试
掘金安东尼1 天前
用 HTMX 为 React Data Grid 加速实时更新
前端·javascript·面试
灵感__idea1 天前
Hello 算法:众里寻她千“百度”
前端·javascript·算法
yinuo1 天前
轻松接入大语言模型API -04
前端
袋鼠云数栈UED团队1 天前
基于 Lexical 实现变量输入编辑器
前端·javascript·架构
cipher1 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
UrbanJazzerati1 天前
非常友好的Vue 3 生命周期详解
前端·面试
AAA阿giao1 天前
从零构建一个现代登录页:深入解析 Tailwind CSS + Vite + Lucide React 的完整技术栈
前端·css·react.js
亦妤1 天前
JS执行机制、作用域及作用域链
javascript
兆子龙1 天前
像 React Hook 一样「自动触发」:用 Git Hook 拦住忘删的测试代码与其它翻车现场
前端·架构