Aman Dhanda
Aman Dhanda

Reputation: 438

React Native - Redux state is updating but component view isn't updating properly

The app has the following functionality.

Suppose, an action happens on server-side & an order goes from "Open" to "In Progress" status.

Expected Behavior:

Now, the user swipes down and refreshes the tab component. On refresh, it should fetch the orders updated data from the server and update the redux orders state. As soon as the orders state updates, all tabs data should be updated automatically.

Actual Behavior:

The user swipes down and refreshes the tab component. On refresh, it fetches the orders updated data from the server and updates the redux orders state. But after updating the state, the component view doesn't update appropriately. I mean, some part updates but some part doesn't update.

I guess, I am not updating the state properly in reducer. Following is the reducer code to GET and PUT the orders payload.

const orders = (state = {}, action)=> {
  switch(action.type){
    case 'GET_ORDERS':
      return action.payload
    case 'PUT_ORDERS':{
      let newState = state;
      if(action.payload != undefined){
        action.payload.map(function(order, index){
          if(newState[order.id] != undefined) {
            newState[order.id].order_status = order.order_status;
          } else {
            newState[order.id] = order;
          }
        });
      }
      return Object.assign({}, state, action.payload);
    }
  }
}

I am maintaining the key of the order object by assinging the order id as key. It's because, due to refresh if new order come, keys should not be reassigned.

Upvotes: 0

Views: 1284

Answers (1)

Jacob
Jacob

Reputation: 78850

You are mutating your orders rather than changing them into new objects. Even though your reducer state is producing new objects, if you have components tied to the order objects, they won't see these as changes. For example, if you have:

const { connect } = require('react-redux');

export function Order({ orderId, order }) {
  return (
    <div className="order">
      <span className="order-id">{order.id}</span>
      <span className="order-status">{order.order_status}</span>
    </div>
  );
}

const mapStateToProps = ({ orders }, { orderId }) => ({
  order: orders[orderId]
});

export default connect(mapStateToProps)(Order);

...then the order prop that's passed to your component will be identified as the same object, and your component won't update.

Try changing your reducer as follows:

const orders = (state = {}, action)=> {
  switch(action.type){
    case 'GET_ORDERS':
      return action.payload
    case 'PUT_ORDERS': {
      const updates = action.payload.map((payloadOrder, index) => {
        const oldOrder = state[payloadOrder.id];
        const newOrder = oldOrder 
          ? { ...oldOrder, order_status: payloadOrder.order_status }
          : payloadOrder;
        return {
          [payloadOrder.id]: newOrder
        };
      });
      return Object.assign({}, state, ...updates);
    }
  }
}

With this change, every order object in your state that has been modified is a new object.

Upvotes: 2

Related Questions