Muzamil Hussain
Muzamil Hussain

Reputation: 33

InitialState not updated in React-Redux

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

Answers (2)

Paveloosha
Paveloosha

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

MorKadosh
MorKadosh

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

Related Questions