2016-01-06 15 views
7

Sto usando Redux e vorrei impostare un flag nello stato se l'utente ha modificato i dati.Accesso ad altre parti di stato nel riduttore di Redux

Prima sto idratante mio deposito con alcuni dati dal server:

let serverData = {toggle: true} 
const store = configureStore({data: serverData, originalData: serverData}) 

Ho poi ho un paio di riduttori:

function data(state = {}, action) { 
    switch (action.type) { 
    case TOGGLE: 
     return { 
     ...state, 
     toggle: !state.toggle 
     } 
    default: 
     return state 
    } 
} 

function changed(state = false, action) { 
    // This doesn't work; we are actually comparing state.changed.originalData and state.changed.data 
    return isEqual(state.originalData, state.data) 
} 

const rootReducer = combineReducers({ 
    data, 
    originalData: (state={}) => state, 
    changed 
}) 

Quello che mi piacerebbe fare qui è impostare la changed flag su true se state.data non equivale più a state.originalData. Tuttavia, utilizzando combineReducers, non riesco ad accedere a queste parti dello stato all'interno del mio riduttore changed.

Qual è il modo più idiomatico per farlo?

+1

È difficile dire cosa stai cercando di fare dall'esempio, ma mi sembra che tu stia usando 'combineReducers' per un'attività che non è stata pensata per gestire. Detto questo, per un commento generale sul problema, controlla https: // github.com/rackt/redux/issues/601 # issuecomment-133519377 –

+1

Grazie, non penso che mi aiuti molto, purtroppo. Come caso d'uso per me: Voglio mostrare un avviso "Hai modifiche non salvate" quando un utente modifica qualcosa su una pagina. Se poi procede a riportare il contenuto nello stato originale, questo messaggio dovrebbe scomparire. Sto lottando per farlo con l'idioma di Redux di vedere ogni riduttore vedere un pezzo di stato separato; Ho bisogno di un riduttore per confrontare due pezzi di stato separati. –

risposta

6

Michelle ha ragione, per estenderlo in termini di flusso tradizionale, pensa a un riduttore come a un negozio, hai appena definito uno dei tuoi "dati" dei negozi e un altro "cambiato" - non è semantico e mostra che probabilmente sei confuso riguardo come sono usati

tuo changed riduttore si suppone che sia tornare allo stato non modificato, oppure, se è stata fatta un'azione che è interessato a, restituire il prossimo Stato. Non è per capire se il tuo negozio è cambiato - questo è ciò che è subscribe.

const unsubscribe = store.subscribe(() => 
    console.log('store was changed:', store.getState()) 
) 

Quando si chiama combineReducers chiamerà ogni riduttore di una volta, con un'azione di @@redux/INIT - ma non preoccuparti di che come è interna. La cosa importante da capire è che sotto ogni tasto del riduttore, lo stato è inizializzato. Nel tuo caso hai inizializzato data in un oggetto vuoto, changed in falso, e originalData in un oggetto vuoto.

Successivamente, quando hai chiamato createStore hai detto "Aggiorna i dati" e "originalData" con questo stato iniziale dal server ". Quindi ora lo stato dei depositi "data" e "serverData" è uguale a {toggle: true}.

A questo punto entrambi gli oggetti sono uguali.

Successivamente quando si chiama store.dispatch tutti i riduttori saranno chiamati in modo che possano avere la possibilità di modificare lo stato (e restituire un nuovo oggetto) sotto ogni riduttore chiave. Ogni riduttore ha solo accesso al proprio stato. Pertanto nel tuo riduttore changed non puoi controllare l'uguaglianza generale dell'oggetto del tuo intero stato in quel modo.

Tuttavia è possibile verificare la presenza di uguaglianza oggetto nella sottoscrizione (misto ES5/6 qui per Chrome 47)

'use strict'; 

const serverData = {toggle: true}; 
const TOGGLE = 'TOGGLE'; 

function data(state, action) { 
    state = state || {}; 
    switch (action.type) { 
    case TOGGLE: 
     return Object.assign({}, state, { 
     toggle: !state.toggle 
     }) 
    default: 
     return state 
    } 
} 

function originalData(state) { 
    state = state || {}; 
    return state; 
} 

const rootReducer = Redux.combineReducers({ 
    data, 
    originalData 
}); 

const store = Redux.createStore(rootReducer, {data: serverData, originalData: serverData }); 

const unsubscribe = store.subscribe(() => 
    console.log('on change equal?', store.getState().data === store.getState().originalData) 
) 

console.log('on load equal?', store.getState().data === store.getState().originalData); 

store.dispatch({ type: TOGGLE }); 

L'uscita console.log dovrebbe essere:

on load equal? true 
on change equal? false 

Fiddle: https://jsfiddle.net/ferahl/5nwfqo9k/1/

+1

I ragazzi chiedono, è chiaro nella domanda. Come può un riduttore accedere a dati di altri stati? Prova a risolvere il problema, ma prova a rispondere alla domanda ... "Accedi ad altre parti di stato in Redux reducer" –

Problemi correlati