Jatin Parmar
Jatin Parmar

Reputation: 2910

React Redux : My React component not receive updated array as props

i have redux store,which contains notifications as an array,now my problem is that my code to add new notification within existing array work fine ,that is store is updated successfully but my component which get notification as props using mapStateToProps function ,always receives an initial state of notification array,so when new notification is added to store its not received by my component, now when i convert my notification from array to a string then its get the updated value, anybody can help find out what i doing wrong? following is my code:

store.js

const initialState={
       //not working when its an arrray 
       notifications:[],//same things work if i assign some string value like 'no notifiation'
  }

function mainReducer(state=initialState,action){
    return {
     notifications:setNotification(state,action)
    }
}



function configureStore(){
    return createStore(
      mainReducer,
      initialState,
      compose(
          applyMiddleware(thunk),
           window.devToolsExtension ? window.devToolsExtension() : f => f
      )
   );
}

 const store=configureStore();
 export default store;

my reducer

        export function setNotification(state,action){
            let notifications=state.notifications;
            switch(action.type){
                case SET_NOTIFICATION:
                     //this is not working ,means store is updated but component is not
                    notifications.push(action.payload);
                    //same will work if payload is string 
                    //notification=action.payload;//assume payload is string
                    break;
            }
            return notifications;
        }

my component

        class Notification extends React.Component{
            constructor(props){
                super(props);
                this.state={}
            }
            render(){
                //this is not working when notification is an array 
                return <h1 style={{marginTop: '170px'}}>this is notification component {this.props.notifications.length}</h1>
                //this is working when notification is string
                //         return <h1 style={{marginTop: '170px'}}>this is notification component {this.props.notifications}</h1>
            }
        } 
        function mapStateToProps(state){
            let notifications=state.notifications
            return {"notifications":notifications};
        }
        function mapDispatchToProps(dispatch){
            return {};
        }
        export default connect(mapStateToProps,mapDispatchToProps)(Notification)

Upvotes: 2

Views: 329

Answers (2)

Pavlos Karalis
Pavlos Karalis

Reputation: 2976

To start, the entire reducer should be rewritten as:

export function setNotification(state,action){
    switch(action.type){
        case SET_NOTIFICATION:
            return {notifications:[...state.notifications,action.payload]}
        default:
            return state;
    }
}

Upvotes: 0

buzatto
buzatto

Reputation: 10382

you are violating redux principle, you are mutating state when you should return a new one. your reducers should always return a new next state (or the same original) not a mutated one.

also when you have an array and do a push to it, though you are adding new values to it, its reference keep the same. hence it's natural to see the same initial value since redux wont go deep compare, its reference is the same so everything looks equal to redux.

your reducer should be more like:

export function setNotification(state, action){
  switch(action.type){
    case SET_NOTIFICATION:
      // using spread is a normal approach but you could use javascript functions to create new objects and arrays
      return { ...state, notifications: [...state.notifications, action.payload] }
    default:
      return state;
  }
}

also your map state to props could be cleaner imo. I don't see often state.get() pattern (not even at docs) and you dont need to pass mapDispatchToProps if you are not using it:

    const mapStateToProps = ({ notifications }) => ({ notifications });
    export default connect(mapStateToProps)(Notification)

Upvotes: 2

Related Questions