我的主应用程序有两个子组件,两个子组件都接收相同的 model
属性。
第一个子组件处理来自 model.myNumberProperty
的数字属性,第二个子组件处理来自 model.myArrayProperty
的数组属性
更改子组件一中的 model.myNumberProperty
会触发重新渲染,但
更改子组件二中的 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 或其他第 3 方库。
请注意,我的模型是一个卡住对象以强制封装,因此我不能只重新创建整个对象。示例中的模型是一个简化的模型,在我的实际项目中,它是一个处理大量数组的复杂纸牌游戏对象。
最佳答案
调用 setState
时,React 会生成 shallow comparison与之前的状态并决定渲染阶段是否应该继续。
在您的情况下,它具有相同的引用,因此不会触发渲染。
要修复此问题,请将数组的副本设置为新状态。
const onButtonTwoClick = () => {
props.dataObject.modifyPropTwo();
// v Make a new copy.
setPropTwo([...props.dataObject.propTwo()]);
};
关于javascript - 当数组 prop 更改时,React 子组件不会重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576702/