2016-03-19 15 views
5

Jakie są zalety korzystania z Reakcji (i opcjonalnie Redux) przy użyciu Immutable? W Redux, mogę po prostu użyć odpoczywać w moim reduktorów, aby powrócić nowy stan:React, Redux i 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, 
     }; 
     // ... 

Jedyny scenariusz Znalazłem to użyteczne było to:

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

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

i że może być nawet nadużywając go, o ile wiem.

Może ktoś mógłby mnie oświecić z korzyści płynących z używania Niezmiennego w kontekście React i Redux?

Odpowiedz

5

Istnieje great video na temat korzyści i implementacji niezmiennych danych, od przemówienia Lee podczas konferencji React Conf 2015. Jeśli chodzi o dane niezmienne i reagowanie, uważam to za istotne przeglądanie.

Poza tym, oto kilka własnych przemyśleń w tej sprawie.

Kod terser

Im bardziej skomplikowana twój stan, tym trudniej jest zarządzać z literałów i operatora rozprzestrzeniać. Wyobraźmy sobie, że zamiast być płaski, trzeba było kilka poziomów stanu zagnieżdżonego:

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

Mimo to nadal można użyć operatora spread, to zaczyna być nużące.

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

Teraz spójrz na odpowiednik w pliku Immutable.js.

import { Map } from 'immutable'; 

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

Następnie możemy użyć trwałego API, aby dokonać głębokich zmian w strukturze.

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

Warto nadmienić, że w zależności od kształtu państwa może być bardziej sensowne dzielenie i zagnieżdżanie reduktorów.

Sharing Structural

Po dokonaniu modyfikacji obiektu z ImmutableJS że korzysta z faktu, że jest on realizowany z hash odwzorowane wektor stara się dzielić najbardziej struktury między starego obiektu i zmodyfikowanej wersji.

Podczas korzystania z operatora rozprzestrzeniania do tworzenia nowych literałów, jesteś zmuszony skopiować więcej danych, niż potrzebujesz do wytworzenia nowego obiektu.

Bezpieczeństwo

można wyeliminować ogromną klasę błędów poprzez zagwarantowanie, że obiekt nie może być zmutowany.

W stanie zmiennym możliwe jest przekazanie odwołania do obiektu do innego kodu, który może go zmutować. Mutowanie obiektu nie jest "błędem", więc nie zostaniesz poinformowany, że to się zmieniło, a także nie będzie śladu stosu, co oznacza, że ​​bardzo trudno jest ustalić, skąd pochodzi mutacja.

Gdziekolwiek są twoje niezmienne obiekty, będą bezpieczne.

Wydajność

Można użyć niezmiennej struktury danych do bardziej zaawansowanych decyzje o tym, czy należy aktualizować składniki, czy też nie.

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

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

Chociaż te rodzaje głębokich porównań może wydawać się drogie, one uniemożliwić konieczności diff lub dotknij DOM gdy przedmioty nie uległy zmianie.

Będzie to jeszcze bardziej skuteczne, jeśli twoje rekwizytki będą niezmiennymi obiektami, ponieważ fromJS nie będzie musiał odtwarzać zagnieżdżonych poziomów.

+0

Świetna odpowiedź, Dan! To naprawdę pomaga mi lepiej zrozumieć Niezmienny. Nie byłem pewien, czy używać "Map", czy "Record", ani jak korzystać z tych rzeczy. Uważam, że dokumentacja jest trochę myląca. Zastanawiam się, dlaczego zdecydowali się użyć formatu '.setIn (['core', 'tracker', 'activeTrackId'], value)' w przeciwieństwie do '.setIn ('core.tracker.activeTrackId', value)'. – ffxsam

+0

Jeśli wolisz ten styl zapisu, istnieją biblioteki takie jak [dot-prop-immutable] (https://github.com/debitoor/dot-prop-immutable). –

+0

PS: Jeszcze krócej, możesz po prostu użyć 'Immutable.fromJS' i przekazać cokolwiek, a on ustawi odpowiednią ilość map i list dla ciebie. – ffxsam

1

Jeśli jesteś ostrożny, aby nie mutować przekazanej właściwości, nie musisz używać pliku Immutable.js.

Od props odniesienie wszelkie zmiany w nim wpłynęłyby na cały wniosek.

Immutable.js gwarantuje, że nie można ich modyfikować, ale ma wpływ na wydajność dużych aplikacji, jeśli nie wykonuje się mutacji, ale korzyścią jest to, że zapobiega przypadkowemu zanieczyszczeniu stanu aplikacji.

Możesz sprawdzić these videos, aby uzyskać szczegółowe wyjaśnienie.

Powiązane problemy