首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >react中state和props的一些坑

react中state和props的一些坑

作者头像
biaoblog.cn 个人博客
发布2025-05-21 09:14:23
发布2025-05-21 09:14:23
14600
代码可运行
举报
运行总次数:0
代码可运行

1.当父组件向子组件传递引用类型数据时,(对象/数组/方法)

如果必须要在子组件修改这个props,需要先把这个props赋值给state,并进行深度拷贝

不然会污染父组件的state,因为没有深度拷贝之前,他们的引用内存地址是一致的,所以就导致父组件和子组件都改变了

超出了props - 只读的预期

相关代码示例:

父组件

代码语言:javascript
代码运行次数:0
运行
复制
import React, { Component } from "react";
import Test from "../components/Test";

class Router2 extends Component {
  constructor(props) {
    super(props);
    this.state = {
      a: [
        {
          value: "1",
        },
      ],

      b: {
        name: "bill",
      },

      show: false,
    };
  }
  render() {
    const { a, show, b } = this.state;
    return (
      <h2>
        Router2
        <div>
          a:
          {a.map((item, index) => {
            return <input type="text" value={item.value} key={index} />;
          })}
          b:
          {b.name}
        </div>
        {show ? (
          <button onClick={() => this.setState({ show: false })}>隐藏</button>
        ) : (
          <button onClick={() => this.setState({ show: true })}>展示</button>
        )}
        {show && <Test a={a} b={b} />}
      </h2>
    );
  }
}

export default Router2;

子组件

代码语言:javascript
代码运行次数:0
运行
复制
import React, { useEffect, useState } from "react";

const Test = ({ a, b }) => {
  const [a_state, setA_state] = useState(a);
  const [b_state, setB_state] = useState(b);

  const setValue = (e) => {
    a_state[0].value = e.target.value;
    setA_state([...a_state]);
  };

  const changeName = () => {
    b.name = `bill pang !!!!!!`;
    let _b = JSON.parse(JSON.stringify(b));
    setB_state(_b);
  };

  useEffect(() => {
    console.log("a__", a);
    console.log("b__", b);
  }, []);

  return (
    <div>
      a_state: <br />
      {a_state.map((item, index) => {
        return (
          <input
            type="text"
            value={item.value}
            key={index}
            onChange={setValue}
          />
        );
      })}
      b_state: <br />
      {b_state.name}
      <button onClick={changeName}>修改名称</button>
    </div>
  );
};

export default Test;

2.react的state更新机制,避免直接修改state(为引用类型的数据)

react 的组件更新,是基于一个**“浅比较”机制**:

  • React 不会对对象/数组做深度对比。
  • 它仅仅比较当前 state 和上一次 state 的引用是否不同(===)
  • 如果 引用没变,React 认为“状态没变”,就不会触发更新。

🔍 举个例子

代码语言:javascript
代码运行次数:0
运行
复制
const [person, setPerson] = useState({ name: "Alice", age: 20 });

const updateAge = () => {
  person.age = 21;       // ❌ 修改了 state 对象的内容
  setPerson(person);     // ❌ 传的还是原来的引用
};

React 会这样判断:

代码语言:javascript
代码运行次数:0
运行
复制
previousState === nextState // 结果是 true,认为“没变”

➡️ React 不会触发组件重新渲染!

但其实你已经偷偷改了内部数据,这就造成了页面和真实数据不一致的问题。

✅ 正确做法

代码语言:javascript
代码运行次数:0
运行
复制
const updateAge = () => {
  setPerson({ ...person, age: 21 }); // ✅ 新的对象引用
};

现在:

代码语言:javascript
代码运行次数:0
运行
复制
previousState === nextState // false,React 检测到“变了”

➡️ React 会重新渲染组件 ✅

总结:

props

不允许,违反数据单向流原则

只能读,不能改

state

改了内容但引用没变 → 无法触发更新

使用新对象/数组引用触发更新

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.当父组件向子组件传递引用类型数据时,(对象/数组/方法)
  • 2.react的state更新机制,避免直接修改state(为引用类型的数据)
  • 🔍 举个例子
  • ✅ 正确做法
  • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档