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

相关推荐
哑巴语天雨13 小时前
React+Vite项目框架
前端·react.js·前端框架
初遇你时动了情14 小时前
react 项目打包二级目 使用BrowserRouter 解决页面刷新404 找不到路由
前端·javascript·react.js
码农老起14 小时前
掌握 React:组件化开发与性能优化的实战指南
react.js·前端框架
前端没钱15 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
高山我梦口香糖18 小时前
[react] <NavLink>自带激活属性
前端·javascript·react.js
撸码到无法自拔18 小时前
React:组件、状态与事件处理的完整指南
前端·javascript·react.js·前端框架·ecmascript
高山我梦口香糖18 小时前
[react]不能将类型“string | undefined”分配给类型“To”。 不能将类型“undefined”分配给类型“To”
前端·javascript·react.js
乐闻x20 小时前
VSCode 插件开发实战(四):使用 React 实现自定义页面
ide·vscode·react.js
irisMoon0620 小时前
react项目框架了解
前端·javascript·react.js
web150850966411 天前
【React&前端】大屏适配解决方案&从框架结构到实现(超详细)(附代码)
前端·react.js·前端框架