Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-redux store updates but React does not

Bear with me here as this question pertains to my first test app using either React, Redux or react-redux. Docs have gotten me far and I have a mock banking app that mostly works. My state object looks roughly like this:

{  activePageId: "checking",  accounts: [   checking: {     balance: 123,     transactions: [       {date, amount, description, balance}     ]   }  ] } 

I have just two actions:

1. CHANGE_HASH (as in url hash). This action always works as expected and all the reducer does is update the state.activePageId (yes, I'm cloning the state object and not modifying it). After the action, I can see the state has changed in the Redux store and I can see that React has updated.

function changeHash(id) {         return {             type: "CHANGE_HASH",             id: id         } } 

2. ADD_TRANSACTION (form submission). This action never updates React, but it always updates the Redux store. The reducer for this action is updating state.accounts[0].balance and it's adding a transaction object to the array state.accounts[0].transactions. I don't receive any errors, React just doesn't update. HOWEVER, if I dispatch a CHANGE_HASH action React will catch up and display all of the ADD_TRANSACTION state updates properly.

function addTransaction(transaction, balance, account) {     return {         type: "ADD_TRANSACTION",         payload: {             transaction: transaction,             balance: balance,             account: account         }     } } 

My reducer...

    function bankApp(state, action) {         switch(action.type) {             case "CHANGE_HASH":                 return Object.assign({}, state, {                     activePageId: action.id                 });             case "ADD_TRANSACTION":             // get a ref to the account                 for (var i = 0; i < state.accounts.length; i++) {                     if (state.accounts[i].name == action.payload.account) {                         var accountIndex = i;                         break;                     }                 }              // is something wrong?                 if (accountIndex == undefined)  {                     console.error("could not determine account for transaction");                     return state;                 }              // clone the state                 var newState = Object.assign({}, state);              // add the new transaction                 newState.accounts[accountIndex].transactions.unshift(action.payload.transaction);              // update account balance                 newState.accounts[accountIndex].balance = action.payload.balance;                  return newState;             default:                 return state;         } 

My mapStateToProps

    function select(state) {         return state;     } 

What am I missing here? I'm under the impression that React is supposed to update as the Redux storeis updated.

Github repo:

Deployment bank demo

p.s. I lied about not having any errors. I do have a number of warnings

""Warning: Each child in an array or iterator should have a unique "key" prop..."

I'm already giving them a key prop set to it's index. I doubt that has anything to do with my issue though.

like image 259
curiouser Avatar asked Oct 15 '15 04:10

curiouser


People also ask

Why isn't my React component updating?

There are two common reasons why React might not update a component even though its props have changed: The props weren't updated correctly via setState. The reference to the prop stayed the same.

What happens when Redux store updates?

In most apps, the need to update the Redux store arises when data in the backend is updated and we need to update the store to reflect the same changes so that presentation to the frontend is possible without reloading updated data from backend. In most cases it involves add, update, and delete.

How do I refresh Redux state?

Just connect the redux state with the component's state by using useSelector hooks, so the component will automatically re-rendered when the redux state changes.


1 Answers

The problem is in this piece of code:

// clone the state var newState = Object.assign({}, state);           // add the new transaction  newState.accounts[accountIndex].transactions.unshift(action.payload.transaction);  // update account balance newState.accounts[accountIndex].balance = action.payload.balance; 

Cloning the state object doesn't mean you can mutate the objects it is referring to. I suggest you to read more about immutability because this isn't how it works.

This problem and solution to it are described in detail in Redux “Troubleshooting” docs so I suggest you to read them.

https://redux.js.org/troubleshooting

I also suggest you to take a look at Shopping Card example in Flux Comparison for Redux because it shows how to update nested objects without mutating them in a similar way to what you are asking.

https://github.com/voronianski/flux-comparison/tree/master/redux

like image 51
Dan Abramov Avatar answered Sep 25 '22 21:09

Dan Abramov