React突变状态,更新数据(对象或者数组),页面数据不刷新的问题

React 突变状态

​ 刚开始开发时,我们可能会遇到这样的问题,使用useState创建对象或者数组时,setState时,页面未进行更新。这里其实是一个突变状态的问题

  • 什么是突变状态?

    ​ 当我们给setState一个基本数据类型时,state值将会是一个不可变的值

    ​ 更新时,state原始值也不会被更改,而是重新创建一个不可变的的基本数据类型,以触发重新渲染

  • 为什么React不推荐突变状态?

    • 调试:如果你使用console.log 并且不改变状态,你过去的日志将不会被最近的状态破坏修改,你可以清楚的看到渲染之间的状态变化

    • 优化:如果之前的propsstate和下一个状态相同,常见的react优化策略将会跳过本次渲染,如果你从不改变状态,检查变化就会非常的快,如果prevProps === props,react就可以确定它内部并没有发生变化

    • 新功能:react正在构建的新功能依赖将状态视为快照,如果你正在更新过去的状态版本,这会导致无法使用新功能

    • 需求变更:一些需要撤销/重做和显示历史记录的值,在没有突变的情况下更容易执行,这是因为你可以将过去的值保存在副本中,并在适用的情况下重做他们

    • 更简单的实现:因为react不依赖突变,所以它不需要对你的对象做任何处理,不需要劫持你的对象。总是将它们包装到代理中,或者在初始化时像许多“反应式”解决方案那样做其他工作。这也是为什么 react 允许您将任何对象置于状态(无论有多大)而没有额外的性能或正确性陷阱。

  • 如何更合理的更新对象或者数组

    看这样一段代码:

    import React from "react";
    import ShoppingList from './ShoppingList';
    import NewItemForm from './NewItemForm';
    function App({
        const [items,setItems] = React.usestateC['apple','banana']);
        function handleAddItem(value) {
            items.push(value);
        	setItems(items);
        }
        return (
            <div>
            	{items.length > 0 && <ShoppingList items={items}/>}
                <NewItemForm handleAddItem={handleAddItem}/>
            </div>
        )
    }
    export default App;
    

    ​ 每当增加一个新项目时,handleAddItem 函数就会被调用。但是,它并不起作用!当我们输入一个项目并提交表单时,该项目没有被添加到购物清单中

    ​ 问题就在于我们违反了 React 中最核心的原则 —— 不可变状态React依靠一个状态变量的地址来判断状态是否发生了变化。当我们把一个项目推入一个数组时,我们并没有改变该数组的地址,所以 React 无法判断该值已经改变。从技术上讲可以改变对象或者数组本身的内容,我们将其称之为突变,然而,react的状态在技术上是可变的,但react仍然推荐使用不可变的方式去改变react的状态。像基本数据类型一样,去始终替换他们,而不是去改变他们

    正确的做法:

    function handleAddItem(value) {
      const nextItems = [...items, value];
      setItems(nextItems);
    }
    

    ​ 不建议修改一个现有的数组,而是从头开始创建一个新的数组。这里的区别在于编辑一个现有的数组和创建一个新的数组之间的区别。

    ​ 同样的,对于对象类型的数据也是:

    // ❌ 不建议
    function handleChangeEmail(nextEmail) {
      user.email = nextEmail;
      setUser(user);
    }
    
    // ✅ 推荐
    function handleChangeEmail(email) {
      const nextUser = { ...user, email: nextEmail };
      setUser(nextUser);
    }
    
如果在React项目中,每个数组数据都需要调用接口,而且这个操作导致页面卡顿,可能是因为接口请求的频率过高,导致页面性能下降。 为了解决这个问题,你可以采取以下一些优化策略: 1. 批量请求:尝试将多个数据的接口请求合并成一个请求。这样可以减少请求的次数,提高性能。你可以使用类似`Promise.all`的方法来同时发送多个请求,并在所有请求完成后再更新页面。 2. 分页加载:如果数据量较大,你可以将数据分页加载,每次加载一部分数据,而不是一次性加载全部数据。这样可以减少一次性请求大量数据所带来的性能问题。 3. 节流函数:使用节流函数来控制接口请求的频率。节流函数可以限制一定时间内函数的执行次数,避免过于频繁的接口请求导致页面卡顿。你可以使用`lodash`库中的`throttle`或者`debounce`函数来实现节流。 4. 缓存数据:如果这些数据相对稳定,不经常变化,你可以考虑将接口返回的数据进行缓存。当页面再次渲染时,先从缓存中读取数据,而不是再次调用接口请求数据。 5. 使用虚拟列表:如果列表数据很长,你可以考虑使用虚拟列表技术,只渲染当前可视区域的数据,而不是全部渲染。这样可以减少DOM元素的数量,提高页面的渲染性能。 通过以上优化策略,你可以改善React项目中大量接口请求导致页面卡顿的问题。根据你的具体情况选择适合的优化方案,并进行实施。希望对你有所帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘎嘎油

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值