惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
V
Visual Studio Blog
罗磊的独立博客
爱范儿
爱范儿
J
Java Code Geeks
博客园 - 司徒正美
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
美团技术团队
小众软件
小众软件
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
博客园 - 聂微东
云风的 BLOG
云风的 BLOG
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Jina AI
Jina AI
Y
Y Combinator Blog
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
Vercel News
Vercel News

博客园 - ฅ˙-˙ฅ

js中常见内存泄漏和场景 用display实现效果:上面根据内容自适应高度;下面撑满所有,并且超出时候显示滚动条 react umi model使用注意事项 拖动改变顺序 博文阅读密码验证 - 博客园 antd input控制只能输入数字并进行格式化显示(antd 3版本) react函数式组件:父组件调用子组件方法 react form表单中自定义组件的数据双向绑定实现 vue3+vant h5: Rem 移动端布局适配之postcss-pxtorem和lib-flexible 项目记录文档 前端mock方案:使用json-server mac安装使用nginx 博文阅读密码验证 - 博客园 umi修改antd主题颜色(通过less文件修改) 部署一个vue项目到阿里云服务器 vue项目通过点击按钮实现复制图片(非图片url和base64),可发送到聊天框 vue重新刷新当前路由(非浏览器强刷,不会出现闪屏) 使用Vue.extend实现iview Upload在单文件上传时,拖拽多个文件给出错误提示 uni-app怎么使用路由守卫,并且路由配置和pages.json中只写一套 uni-app小程序iPhone X适配底部栏黑横线 使用css自定义变量实现实现主题切换功能
react更改多层对象变量的方法
ฅ˙-˙ฅ · 2026-02-03 · via 博客园 - ฅ˙-˙ฅ

以下是我的测试组件中:

import React, { useEffect, useState } from 'react';

export default function Home() {
  const [obj, setObj] = useState({ a: { t: 1 }, b: { t: 333 } })
  { console.log(1111, '重新执行') }
  const ceshi = () => {
    setObj(pre => ({
      ...pre,
      a: {
        ...pre.a,
        t: pre.a.t + 1
      }
    }));
    /*
  setObj(pre => {
      const newObj = { ...pre }
      newObj.a.t = 55;
      return newObj;
    });
  */
    // const objNew = JSON.parse(JSON.stringify(obj));
    // objNew.a.t = objNew.a.t + 1;
    // setObj(objNew);
  }
  useEffect(() => {
    console.log("🚀 ~ Home ~ obj:", obj)
  }, [obj])

  useEffect(() => {
    console.log("🚀 ~ Home ~ 具体字段a:", obj.a)
  }, [obj.a])
  useEffect(() => {
    console.log("🚀 ~ Home ~ 具体字段b:", obj.b)
  }, [obj.b])
  return <>
    {console.log(1111, '重新渲染')}
    <div onClick={ceshi}>ceshi-{obj.a.t}-{obj.b.t}</div>
  </>;
}
  1. 使用JSON.parse(JSON.stringify(obj))深度克隆
    深度克隆每个key引用都变,以上三个useEffect监听都能监听到
    但是性能差,还可能数据丢失
    如果我子组件b只传入了obj.b,即使b组件使用了memo;这样修改a的时候b组件也会重新执行
setObj(pre => ({
      ...pre,
      a: {
        ...pre.a,
        t: pre.a.t + 1
      }
    }));

这种只更新了对象中的a,所以obj.b监听不到
3.

setObj(pre => {
      const newObj = { ...pre }
      newObj.a.t = 55;
      return newObj;
 });

这种只更新了obj.a.t, obj.a和obj.b都监听不到,但是页面会更新(以为obj变了组件会重新执行)
4. 使用 Immer

import { produce } from 'immer';

setObj(produce(draft => {
  draft.a.t += 1;
  // b 自动保持原样,Immer 会正确处理
}));

总结,我一般使用2或者3比较多,具体更新整个key,哪个key,还是更新最里面的字段,需要根据业务场景来定;
比如说我子组件a监听属性a,b组件监听属性b,那我希望父组件更新的a属性的时候,b组件监听的b不要执行,那就需要父元素只改a的引用;