React为什么要这样更新数组和对象

更新对象

当你想更新一个对象和数组时,你需要创建一个新的对象(或复制现有的对象),然后用这个副本来更新状态

js 复制代码
import { useState } from 'react'

export default function App() {
    const [person, setPerson] = useState({
        name: '我是柯南',
        artwork: {
          title: '侦探',
          age: 8
        }
    });
    function changeName() {
        setPerson({
          ...person,
          name: '我是新一'
        });
    }
    return (
        <div>
            <div onClick={changeName}>点我修改名字</div>
            <div>{person.name}</div>
        </div>
    )
}

更新状态中的数组

和对象同理,需要创建一个新数组。

js 复制代码
import { useState } from 'react'

const initialList = [
  { id: 0, name: '新一'},
  { id: 1, name: '柯南'},
];

export default function App() {
    const [person, setPerson] = useState(initialList);
    function changeName() {
        setPerson(person.map(item => {
            if (item.id === 0) {
                return { ...item, name: '我不是新一' };
            } else {
                return item;
            }
        }));
    }
    function addName() {
        // 创建一个新数组,并将新元素添加到新数组中
        const newPserson = [...person, {id: person.length + 1, name: `小兰${ person.length + 1}`}]
        // 更新状态以触发重新渲染,并将新数组作为新的状态值
        setPerson(newPserson)
    }
    return (
        <div>
            <div onClick={changeName}>点我修改名字</div>
            <div onClick={addName}>点我加人</div>
            {person.length && person.map(item => <div key={item.id}>{item.name}</div>)}
        </div>
    )
}

React为什么要这样更新数组和对象

React是依赖于引用比较来检测状态变化。当你直接修改现有的数组或对象的内容,无法检测到数组和对象的变化,因为它仅仅是比较引用,如果引用相同,即使数组或对象发生了变化,React认为状态没有发生变化而不会重新去渲染组件。 React为了确保正确检测到状态变化并触发重新渲染,需要创建一个新的数组或对象或复制现有的数组,并对其进行修改,,这样React就能够检测到数组引用的变化,从而更新状态并重新渲染组件。

例如,数组使用 Array.prototype.concat()、展开操作符 ...Array.prototype.slice() 等方法来创建一个新数组,然后对新数组进行修改并更新状态,这样可以确保React能够正确地捕捉到状态的变化。

React18的状态更新

React18引入了一个新的特性,称为"Concurrent Mode"(并发模式),这项特性旨在提高 React 应用的性能和响应能力。在 Concurrent Mode 下,React 18 采用了新的更新机制和渲染优化。,通过异步批量更新、React Fiber架构、Reconciler 和 Renderer 分离。

数据变化监听原理:

  1. 状态(State)更新 :当组件的状态通过 setState 进行更新时,React 会比较新旧状态,然后在合适的时机(在异步批量更新中)触发重新渲染。
  2. 属性(Props)更新:当组件的属性发生变化时,React 会触发更新并重新渲染组件。
  3. 上下文(Context)变化:当上下文中的值发生变化时,依赖于该上下文的组件会重新渲染。

Vue为什么不需要创建新的数组

Vue有一个响应式系统,会追踪属性的变化,必要时触发视图更新。Vue2的响应式系统对于数组的变化使用了重写数组的特定方法,比如数组push方法,Vue 会通知相关的依赖(比如模板中渲染这个数组的部分)需要进行更新,触发视图的重新渲染,以展示最新的数组内容。
在Vue3中,采用了更高效的基于 Proxy 的响应式系统。它可以更精准地捕获数组的变化,包括索引的直接赋值等操作。因此,在Vue3中,你可以直接修改数组的元素,而不必依赖特定的数组方法,Vue 3 的响应式系统会更好地追踪这些变化并触发相应的更新。

相关推荐
程序员小续1 小时前
再也不写 Class:React Hooks 完整实战与最佳实践
前端·javascript·react.js
CF14年老兵2 小时前
从卡顿到飞驰:我是如何用WebAssembly引爆React性能的
前端·react.js·trae
江城开朗的豌豆3 小时前
拆解Redux:从零手写一个状态管理器,彻底搞懂它的魔法!
前端·javascript·react.js
伍哥的传说9 小时前
Mitt 事件发射器完全指南:200字节的轻量级解决方案
vue.js·react.js·vue3·mitt·组件通信·事件管理·事件发射器
随笔记17 小时前
react-router里的两种路由方式有什么不同
前端·react.js
晴空雨20 小时前
React 合成事件原理:从事件委托到 React 17 的重大改进
前端·react.js
@大迁世界20 小时前
useCallback 的陷阱:当 React Hooks 反而拖了后腿
前端·javascript·react.js·前端框架·ecmascript
Fantastic_sj20 小时前
React 19 核心特性
前端·react.js·前端框架
小高00720 小时前
📌React 路由超详解(2025 版):从 0 到 1 再到 100,一篇彻底吃透
前端·javascript·react.js
wwy_frontend21 小时前
React性能优化实战:从卡顿到丝滑的8个技巧
前端·react.js