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 的响应式系统会更好地追踪这些变化并触发相应的更新。

相关推荐
吕彬-前端3 小时前
使用vite+react+ts+Ant Design开发后台管理项目(二)
前端·react.js·前端框架
小白小白从不日白3 小时前
react hooks--useCallback
前端·react.js·前端框架
恩婧3 小时前
React项目中使用发布订阅模式
前端·react.js·前端框架·发布订阅模式
程序员小杨v14 小时前
如何使用 React Compiler – 完整指南
前端·react.js
谢尔登5 小时前
Babel
前端·react.js·node.js
卸任5 小时前
使用高阶组件封装路由拦截逻辑
前端·react.js
清汤饺子8 小时前
实践指南之网页转PDF
前端·javascript·react.js
霸气小男8 小时前
react + antDesign封装图片预览组件(支持多张图片)
前端·react.js
小白小白从不日白9 小时前
react 组件通讯
前端·react.js
小白小白从不日白11 小时前
react hooks--useReducer
前端·javascript·react.js