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 天前
03 渲染机制、性能优化与现代 React
javascript·react.js·性能优化
openKaka_1 天前
为什么 React 18 之后使用 createRoot,而不是 ReactDOM.render
前端·javascript·react.js
老王以为1 天前
从源码到架构:React useActionState 深度剖析
前端·javascript·react.js
天蓝色的鱼鱼1 天前
当AI开始替我写代码,我还要纠结选Vue还是React吗?
vue.js·react.js·ai编程
空中海2 天前
01 React Native 基础、核心组件与布局体系
javascript·react native·react.js
空中海2 天前
05 React架构设计、项目实践与专家清单
前端·react.js·前端框架
空中海2 天前
04 工程化、质量体系与 React 生态
前端·ubuntu·react.js
空中海2 天前
03 性能、动画与 React Native 新架构
react native·react.js·架构
空中海2 天前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js