问题
I'm using react with redux and I'm having problems with a component connected to a list from a store. I have a list that whenever I click it adds an object or deletes it from the list with the action select, and I have a component connected to the state getting the list and rendering differently if the list is empty, length == 1 or >= 1. The list starts empty and when I add the first object the action is carried and the component re-renders, if I trigger the action again the component never renders again but I can see in the console that the next state has all the selected elements. What am I missing?
//Component that executes action:
const mapDispatchToProps = dispatch => {
return {
select: selected => dispatch(select(selected))
};
};
class AnimatedlistComponent extends Component {
constructor(props) {
super(props)
this.state = {selected: {}}
}
onItemClick(d) {
console.log("selected " + d)
let selected = this.state.selected
if (this.state.selected[d.id]) {
delete selected[d.id]
this.props.select(selected)
} else {
selected[d.id] = d
this.props.select(selected)
}
}
render() {
const childElements = this.props.detectors.map(u => {
return (
<ListGroupItem id={'list' + u.id} className='detectorlistElement' key={u.id} style={elementStyle}
onClick={() => this.onItemClick(u)}>
<Glyphicon glyph="tag"/> {u.name}
</ListGroupItem>
);
});
return (
<div>
<p style={headerStyle}><b>Dector list</b></p>
<ListGroup id={"detectorList"}>
{childElements}
</ListGroup>
</div>
);
}
}
export default connect(null,mapDispatchToProps)(AnimatedlistComponent)
// Component that receives prop:
function mapStateToProps(state) {
return {Selected: state.reducer.Selected }
}
@connect(mapStateToProps)
class MiddlePanel extends Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(){
console.log("receive new props")
}
render() {
console.log("render middle")
const Selected = this.props.Selected;
let middlepanel
if (Object.keys(detectorsSelected).length >1) {
middlepanel = <div>mas que uno</div>;
} else if (Object.keys(detectorsSelected).length === 0){
middlepanel = <div>Ninguno</div>
}else if (Object.keys(detectorsSelected).length === 1){
middlepanel = <div>uno</div>
}
return (
<div>
{middlepanel}
</div>
);
}
}
// Action:
export function select(Selected) {
return {
type: types.SELECT,
Selected: Selected
}
};
// Reducer:
Reducer(state = {
Selected: {}
}, action = null) {
switch (action.type) {
case types.SELECT:
return Object.assign({}, state, {Selected: action.Selected});
default:
return state;
}
};
回答1:
I see a few problems with your code, I'll point them out:
1. Inside AnimatedlistComponent you have selected object it in the state but you're not using in the render function and it looks like there's actually no need in it. If you omitted some parts of the render method and you are using the selected object from the state then you should be setting the state once the object is changed.
2. It looks like your AnimatedlistComponent component is half controlled. You're keeping it's data in two places, once in the app state (when using redux to update other components) and once in the component, that isn't a good practice. You should be saving it in one place and keep it synchronized.
3. The problem that causes the issue you're experiencing is actually because you're keeping a reference to the original selected object and not copying it. You should be doing something like: return Object.assign({}, state, {Selected: {...action.Selected}}); in your reducer to get immutability.
Feel free to comment if my response isn't helpful enough.
来源:https://stackoverflow.com/questions/51284989/component-not-receiving-new-props