如果必须要在子组件修改这个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;
react 的组件更新,是基于一个**“浅比较”机制**:
state
和上一次 state
的引用是否不同(===)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
改了内容但引用没变 → 无法触发更新
使用新对象/数组引用触发更新