我有两个子组件的主应用程序,它们都接收相同的model
属性。
第一个子组件处理来自model.myNumberProperty
的数字prop,第二个子组件处理来自model.myArrayProperty
的数组prop
在子组件1中更改model.myNumberProperty
会触发重新渲染,但是
在子组件2中更改model.myArrayProperty
不会
function App() {
const model = MyModel();
return (
<div className="App">
Main app
<ComponentOne dataObject={model} />
<ComponentTwo dataObject={model} />
</div>
);
}
export default function MyModel() {
let _propOne = 0;
let _propTwo = ["one"];
const propOne = () => {
return _propOne;
};
const propTwo = () => {
return _propTwo;
};
const modifyPropOne = () => {
_propOne++;
console.log("modifying prop one", _propOne);
};
const modifyPropTwo = () => {
_propTwo.push("new element");
};
return Object.freeze({ propOne, propTwo, modifyPropOne, modifyPropTwo });
}
const ComponentOne = props => {
const [propOne, setPropOne] = useState(props.dataObject.propOne());
const onButtonOneClick = () => {
props.dataObject.modifyPropOne();
setPropOne(props.dataObject.propOne());
};
return (
<div>
<p>Hello ComponentOne:</p>
<button onClick={onButtonOneClick}>ModifyPropOne</button>
<p>{propOne}</p>
</div>
);
};
const ComponentTwo = props => {
const [propTwo, setPropTwo] = useState(props.dataObject.propTwo());
const onButtonTwoClick = () => {
props.dataObject.modifyPropTwo();
setPropTwo([...props.dataObject.propTwo()]);
console.log('Prop two', props.dataObject.propTwo());
};
return (
<div>
<p>Hello ComponentTwo</p>
<button onClick={onButtonTwoClick}>ModifyPropTwo</button>
{propTwo.map((value, index) => (
<p key={index}>{value}</p>
))}
</div>
);
};
请查看this CodeSandbox进行测试。
我正在使用React Hooks。
我的问题的解决方案应该仅是React,因此没有Redux或其他第三方库。
请注意,我的模型是冻结对象以执行封装,因此我不能只是重新创建整个对象。该示例中的模型是简化后的模型,在我的真实项目中,它是一个复杂的Card游戏对象,可以处理许多数组。
最佳答案
在调用setState
时,React使shallow comparison保持先前的状态,并决定是否应继续进行渲染阶段。
在您的情况下,它具有相同的引用,因此不会触发渲染。
要修复它,请将阵列的副本设置为新状态。
const onButtonTwoClick = () => {
props.dataObject.modifyPropTwo();
// v Make a new copy.
setPropTwo([...props.dataObject.propTwo()]);
};
请参阅The power of not mutating Data。