我目前正在尝试与Redux结合使用React并遇到一个奇怪的问题:
如果状态的一个属性被更改,则视图将在组件中更新。如果另一个属性已更改,则不会更新-除非我再次更新第一个属性。我将尝试使其更加清晰:
这是商店界面:
export interface StoreState {
counter: number;
rectangles: Rectangle[];
}
这是减速器:
export function enthusiasm(state: StoreState, action: EnthusiasmAction): StoreState {
switch (action.type) {
case INCREMENT_ENTHUSIASM:
return { ...state, counter: state.counter + 1 };
case DECREMENT_ENTHUSIASM:
return { ...state, counter: Math.max(1, state.counter - 1) };
case ADD_RECTANGLE:
let updatedRectangles: Rectangle[] = [];
if(state.rectangles){
updatedRectangles = state.rectangles;
}
updatedRectangles.unshift(action.payload);
return {...state, rectangles: updatedRectangles};
default:
return state;
}
}
这是包装组件的容器:
export function mapStateToProps(state: StoreState) {
return {
enthusiasmLevel: state.counter,
rectangles:state.rectangles,
}
}
export function mapDispatchToProps(dispatch: Dispatch<actions.EnthusiasmAction>) {
return {
onIncrement: () => dispatch(actions.incrementEnthusiasm()),
onDecrement: () => dispatch(actions.decrementEnthusiasm()),
addRectangle: () => dispatch(actions.addRectangle({posX: Math.floor(Math.random() * 100), posY: Math.floor(Math.random() * 100), id: Math.floor(Math.random() * 1000)}))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Hello);
这是我要渲染的组件:
function Hello({ counter = 1, rectangles = [], onIncrement, onDecrement, addRectangle }: Props) {
console.log(counter, rectangles);
return (
<div className="hello">
<button onClick={onDecrement}>-</button>
<button onClick={onIncrement}>+</button>
<button onClick={addRectangle}>+</button>
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
{
rectangles.map((rectangle: Rectangle) => {
return <Rect
key={rectangle.id}
x={rectangle.posX}
y={rectangle.posY}
width={150}
height={150}
fill={'green'}
draggable
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
/>
})
}
</Layer>
</Stage>
</div>
);
}
当我增加计数器时,视图将更新并记录状态。
当我调用addRectangle时,即使状态已更改,视图也不会更新(并且状态未记录在组件中):
现在,当我再次增加计数器时,该视图最终将得到更新,并且之前添加的所有矩形都将添加到该视图中(并再次记录状态):
由于我是新来的反应者,因此问题似乎很明显,但是我无法弄清楚我做错了什么。非常感谢您的帮助,谢谢!
您正在变异state.rectangles
。如果状态不变,则Redux会跳过渲染。您应该改为创建一个新数组。在redux文档中对此进行了解释:更新嵌套对象
常见错误#1:指向相同对象的新变量
定义新变量不会创建新的实际对象-只会创建对同一对象的另一个引用。
在这种情况下,我们的问题是这updatedReactangles
不是一个新数组。
case ADD_RECTANGLE:
let updatedRectangles: Rectangle[] = [];
if(state.rectangles){
updatedRectangles = state.rectangles; // still the same array
}
updatedRectangles.unshift(action.payload);
return {...state, rectangles: updatedRectangles};
尝试这样的事情:
case ADD_RECTANGLE:
let updatedRectangles: Rectangle[] = [];
if(state.rectangles){
updatedRectangles = state.rectangles.slice(); // shallow copy
}
updatedRectangles.unshift(action.payload);
return {...state, rectangles: updatedRectangles};
该...
运营商可以让这个错误更容易避免。由于没有诸如此类的变异方法Array.unshift()
,因此我们可以确保我们不会无意间破坏了先前的状态。
case ADD_RECTANGLE:
return {
...state,
rectangles: [...state.rectangles, action.payload],
}
但是要确保它state.rectangles
始终是一个数组,而不要undefined
通过向reducer提供默认的初始状态参数来确保。
function reducer(state={ rectangles: [] }, action) {
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句