2016-03-19 35 views
5

Quali sono i vantaggi dell'utilizzo di Immutable con React (e facoltativamente, Redux)? In Redux, posso semplicemente utilizzare riposare nei miei riduttori per restituire un nuovo stato:React, Redux e Immutable

const initialState = { 
    activeTrackId: '', 
    state: 'stopped', 
}; 

export default function (state = initialState, action) { 
    switch (action.type) { 
    case actions.PROCESS_TRACK_ACTION: 
     return { 
     ...state, 
     activeTrackId: action.state !== 'stopped' ? action.track._id : '', 
     state: action.state, 
     }; 
     // ... 

L'unico scenario che ho trovato utile in stato questo:

shouldComponentUpdate(nextProps) { 
    const oldProps = Immutable.fromJS(this.props); 
    const newProps = Immutable.fromJS(nextProps); 

    return !Immutable.is(oldProps, newProps); 
} 

e che potrebbe persino essere abusando di esso, per quanto ne so.

Forse qualcuno potrebbe illuminarmi sul vantaggio dell'utilizzo di Immutable nel contesto di React e Redux?

risposta

5

C'è uno great video sui vantaggi e le implementazioni per i dati immutabili, dal discorso di Lee al React Conf 2015. Per quanto riguarda il pensiero su Immutable Data e React, considererei la visione essenziale.

A parte questo, ecco alcuni dei miei pensieri in merito.

Codice terser

Più complesso il tuo stato diventa, più diventa difficile da gestire con letterali e l'operatore diffusione. Immaginate che invece di essere piatta, hai avuto un paio di livelli di stato nidificato:

const initialState = { 
    core: { 
    tracker: { 
     activeTrackId: '', 
     state: 'stopped' 
    } 
    } 
}; 

Anche se è ancora possibile utilizzare l'operatore diffusione, comincia a diventare noioso.

return { 
    ...state, 
    core: { 
    ...state.core, 
    tracker: { 
     ...state.core.tracker, 
     activeTrackId: action.state !== 'stopped' ? action.track._id : '', 
     state: action.state 
    } 
    } 
}; 

Ora guarda l'equivalente con Immutable.js.

import { Map } from 'immutable'; 

const initialState = Map({ 
    core: Map({ 
    tracker: Map({ 
     activeTrackId: '', 
     state: 'stopped' 
    }) 
    }) 
}); 

Quindi possiamo utilizzare l'API persistente per apportare modifiche profonde alla struttura.

return state 
    .setIn(
    ['core', 'tracker', 'activeTrackId'], 
    action.state !== 'stopped' ? action.track._id : '' 
) 
    .setIn(
    ['core', 'tracker', 'state'], 
    action.state 
); 

Vale la pena ricordare che a seconda della forma del vostro stato, potrebbe avere più senso per dividere e nido vostri riduttori, invece.

condivisione strutturale

Quando si effettua una modifica ad un oggetto con ImmutableJS si avvale del fatto che è implementato con hash mappato vettore cerca di condividere la maggior parte della struttura tra l'oggetto vecchio e la versione modificata.

Quando si utilizza l'operatore di spread per creare nuovi valori letterali, si è costretti a copiare più dati di quelli necessari per produrre un nuovo oggetto.

sicurezza

È possibile eliminare una grande classe di bug, garantendo che l'oggetto non può essere mutato.

Con lo stato mutabile, è possibile passare un riferimento a un altro codice, che potrebbe mutarlo. La mutazione di un oggetto non è "un errore", quindi non ti verrà detto che è cambiato e non ci sarà traccia di stack, il che significa che può essere molto difficile capire da dove provenga la mutazione.

Ovunque i tuoi oggetti immutabili vadano, saranno al sicuro.

prestazioni

È possibile utilizzare le strutture di dati immutabili di prendere decisioni più avanzati sul fatto che per aggiornare i componenti o meno.

shouldComponentUpdate(nextProps) { 
    const oldProps = Immutable.fromJS(this.props); 
    const newProps = Immutable.fromJS(nextProps); 

    return !Immutable.is(oldProps, newProps); 
} 

Anche se questi tipi di confronti profonde potrebbero sembrare costoso, che ti impedisce di dover diff o toccare il DOM quando gli oggetti non sono cambiate.

Questo sarà ancora più efficace se i tuoi oggetti di scena sono oggetti immutabili, poiché fromJS non dovrà ricreare i livelli nidificati.

+0

Ottima risposta, Dan! Questo in realtà mi aiuta a capire di più Immutabile. Non ero sicuro se usare 'Map', o' Record', o come usare anche queste cose. Trovo la documentazione un po 'confusa, a volte. Mi chiedo perché hanno scelto di utilizzare un formato come '.setIn (['core', 'tracker', 'activeTrackId'], value)' al contrario di '.setIn ('core.tracker.activeTrackId', value)'. – ffxsam

+0

Se preferisci questo stile di notazione, ci sono librerie come [dot-prop-immutable] (https://github.com/debitoor/dot-prop-immutable). –

+0

PS: Anche più breve, puoi semplicemente usare 'Immutable.fromJS' e passarlo qualsiasi cosa, e ti imposterà la giusta quantità di mappe ed elenchi. – ffxsam

1

Se si fa attenzione a non mutare la proprietà passata, non è necessario utilizzare Immutable.js.

Poiché il codice props fa riferimento a qualsiasi modifica apportata, ciò influirebbe sull'intera applicazione.

Immutable.js garantisce che non possono essere modificati ma ha un impatto sulle prestazioni su app di grandi dimensioni se non si sta effettuando la mutazione, ma il vantaggio è che impedisce qualsiasi inquinamento accidentale dello stato dell'applicazione.

È possibile controllare these videos per una spiegazione approfondita.

Problemi correlati