2015-10-15 17 views
29

Gestisci qui come questa domanda riguarda la mia prima app di test utilizzando React, Redux o react-redux. I documenti mi hanno portato lontano e ho una finta app bancaria che funziona per lo più. Il mio oggetto di stato si presenta più o meno così:React-redux aggiorna gli aggiornamenti ma React no

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

Ho solo due azioni:

1. CHANGE_HASH (come in url hash). Questa azione funziona sempre come previsto e tutto ciò che fa il riduttore è aggiornare lo stato.activePageId (sì, sto clonando l'oggetto stato e non lo modificando). Dopo l'azione, posso vedere lo stato è cambiato nel negozio Redux e posso vedere che React è aggiornato.

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

2. ADD_TRANSACTION (modulo di presentazione). Questa azione non aggiorna mai React, ma aggiorna sempre l'archivio Redux. Il riduttore per questa azione sta aggiornando state.accounts [0] .balance e aggiunge un oggetto transazione allo stato array.accounts [0] .transactions. Non ricevo errori, React non si aggiorna. TUTTAVIA, se invio un'azione CHANGE_HASH, React raggiungerà e visualizzerà tutti gli aggiornamenti dello stato ADD_TRANSACTION correttamente.

funzione addTransaction (transazione, equilibrio, conto) { ritorno { tipo: "ADD_TRANSACTION", payload: { transazione: transazione, equilibrio: equilibrio, conto: conto } } }

mio riduttore ...

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; 
    } 

miei mapStateToProps

012.
function select(state) { 
    return state; 
} 

Cosa mi manca qui? Ho l'impressione che React debba aggiornarsi man mano che il negozio Redux viene aggiornato.

Github repo: https://github.com/curiousercreative/bankDemo Distribuzione: http://curiousercreative.com/demos/bankDemo/

P.S. Ho mentito sul fatto di non avere errori. Ho un numero di avvertenze "" Attenzione: ogni bambino in un array o iteratore dovrebbe avere un puntello "chiave" univoco ... "Sto già dando loro un puntello chiave impostato sul suo indice. Dubito che abbia qualcosa da fare con il mio problema però

+1

Hmm, penso due cose aiuteranno a restringere il bug: 1) usa [Redux-logger] (https://github.com/fcomb/redux-logger) per vedere cosa è cambiato quando l'azione accade 2) inserisci il tuo codice riduttore, azione e mapStateToProps. – Cheng

+0

Sfortunatamente, non ero in grado di far funzionare il redux-logger, ma ho registrato le cose da solo e le cose funzionano come previsto. Aggiornerò la domanda ora con riduttore, azioni e mapStateToProps. – curiouser

+0

In che modo React determina se lo stato è cambiato? Forse perché il cambiamento è abbastanza profondo nell'oggetto di stato e il cambiamento è così piccolo che non viene re-rendering? Come reagisce-redux decidere se aggiornare i puntelli React? Ho appena disconnesso il valore di stato in mapStateToProps e viene aggiornato lì, non solo in React. – curiouser

risposta

44

il problema è in questo pezzo di codice:..

 // 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; 

clonazione l'oggetto stato non significa che si può mutare gli oggetti a cui fa riferimento io suggerisco di leggere di più circa immutabilità perché non è così che funziona

Questo problema e la soluzione ad esso sono descritti in dettaglio nella documentazione di "Risoluzione dei problemi" di Redux quindi consiglio di leggerli.

https://redux.js.org/troubleshooting

Propongo inoltre di dare un'occhiata a esempio Shopping Card in Flux confronto per Redux perché mostra come aggiornare gli oggetti nidificati senza mutare in un modo simile a quello che si sta chiedendo.

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

+7

Grazie! Avevo letto quei documenti e avevo tentato di preservare l'oggetto statale, tuttavia il mio fraintendimento è nel metodo Object.assign. Mentre questo stava creando un nuovo oggetto dall'oggetto iniziale, era solo un clone superficiale che significa che gli oggetti nidificati nell'oggetto di stato non erano clonati ma facevano ancora riferimento agli oggetti nidificati degli oggetti di stato originali. Non stavo correndo in questa proprietà con un'altra azione perché nessun oggetto nidificato veniva modificato. Un buon resoconto sulla clonazione di oggetti (il n. 5 è quello che mi ha procurato): http://blog.soulserv.net/understanding-object-cloning-in-javascript-part-i/ – curiouser

+7

Questo è corretto. In generale non si vuole fare una clonazione profonda di tutto, anche se è costoso. Basta clonare le parti che cambi. Ridurre i riduttori in molte funzioni per mantenere il codice mantenibile. Puoi trarre ispirazione dall'esempio "carrello della spesa" in Redux repo. –

Problemi correlati