一个前端,爱跑步、爱吉他、爱做饭、爱生活、爱编程、爱南芳姑娘,爱我所爱。世间最温暖又无价的是阳光、空气与爱,愿它们能带你去更远的地方。

  • 文章
  • 心情
  • 照片墙
  • 留言板
  • 工具
  • 友链
  • biaoblog

    专注web开发技术分享

    react中state和props的一些坑

    技术 6 2025-05-19 14:49

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


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

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

    超出了props - 只读的预期

    相关代码示例:


    父组件

    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;
    


    子组件

    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 认为“状态没变”,就不会触发更新。


    🔍 举个例子

    const [person, setPerson] = useState({ name: "Alice", age: 20 });
    
    const updateAge = () => {
      person.age = 21;       // ❌ 修改了 state 对象的内容
      setPerson(person);     // ❌ 传的还是原来的引用
    };
    

    React 会这样判断:

    previousState === nextState // 结果是 true,认为“没变”
    

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


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


    ✅ 正确做法

    const updateAge = () => {
      setPerson({ ...person, age: 21 }); // ✅ 新的对象引用
    };
    

    现在:

    previousState === nextState // false,React 检测到“变了”
    

    ➡️ React 会重新渲染组件 ✅


    总结:


    props

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

    只能读,不能改



    state

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

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

    文章评论

    评论列表(0