Reputation: 33
I am trying to change the state immutably and return a new state but in the UI component new state not changed. The new state values are fetched successfully but not display. I don't understand what is the issue behind.
Anyone has suggestions share me
Here is my reducer:
import * as actionTypes from './actions';
const initialState = {
data: [
{id: 1, name: "accordion1", content: () => {}, status: 1},
{id: 2, name: "accordion2", content: () => {}, status: 0},
{id: 3, name: "accordion3", content: () => {}, status: 0},
]
}
const reducer = (state = initialState, action) => {
debugger;
switch(action.type) {
case actionTypes.ACTIVE_STATE:
debugger;
var newData = state.data;
for(var i= 0; i<newData.length; i++) {
newData[i].status = newData[i].status === 1 ? 0 : 1
}
return {
...state,
data: newData
}
default:
return state;
}
}
export default reducer;
Here is my UI component were not update:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actionTypes from '../store/actions';
class Accordion extends Component {
render() {
debugger;
return (
<div>
{this.props.accordions.map((accordion, index) => {
return (
<div key={index}>
<div>{accordion.status}</div>
<div className={`accordion ${accordion.status}`} onClick={this.props.expandAccordion}>
{accordion.name}
</div>
<div className="panel">
</div>
</div>
);
})}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
accordions: state.data
};
}
const mapDispatchToProps = (dispatch) => {
return {
expandAccordion: () => dispatch({type: actionTypes.ACTIVE_STATE})
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Accordion);
Upvotes: 0
Views: 1285
Reputation: 623
You are actually mutating the state. Try this...
import * as actionTypes from './actions';
const initialState = {
data: [
{id: 1, name: "accordion1", content: () => {}, status: 1},
{id: 2, name: "accordion2", content: () => {}, status: 0},
{id: 3, name: "accordion3", content: () => {}, status: 0},
]
}
const reducer = (state = initialState, action) => {
switch(action.type) {
case actionTypes.ACTIVE_STATE:
return {
...state,
data: state.data.map((acdnObj) => {
return {
...acdnObj,
status: acdnObj.status === 1 ? 0 : 1,
}
}),
}
default:
return state;
}
}
export default reducer;
Upvotes: 0
Reputation: 6006
I assume that the problem is in the following lines:
var newData = state.data;
for(var i= 0; i<newData.length; i++) {
newData[i].status = newData[i].status === 1 ? 0 : 1
}
Why?
Since basically, when you assign var newData = state.data;
you actually copy the object reference, and by that, you don't keep it immutable, and as far for React, which makes shallow comparing, it never changed.
One possible solution would be to change this code to an immutable update:
const newData = state.data.map((entry) => ({...entry, status: entry.status === 1 ? 0 : 1}));
return {
...state,
data: newData
}
P.S: If you want to get smarty pants, you can use XOR for your status update: ({...entry, status: entry.status ^ 1})
Upvotes: 1