2015-08-28 27 views
19

Pracuję nad dużą aplikacją z Redux i React i postanowiłem zrobić kilka komponentów wielokrotnego użytku, takich jak niestandardowe pola wyboru i przyciski opcji.Projektowanie akcji Redux i reduktorów dla komponentu wielokrotnego użytku React

Ponieważ chcę przechowywać te informacje w sklepie Redux, aby móc łatwo debugować stan aplikacji, a ten sam składnik ma wszędzie tę samą funkcjonalność, dobrym pomysłem jest utworzenie reduktorów i akcji dla każdego komponentu.

Jednak reduktory Redux zwracają nowy stan i zapisują go w sklepie z nazwą reduktora jako kluczem, a to zabrania posiadania więcej niż jednego komponentu tego samego typu na tej samej stronie przy użyciu tych samych działań i reduktorów, ale utrzymywanie różne stany.

Myślę, że istnieją dwa rozwiązania tego problemu:

  • tworzyć różne działania i reduktory dla każdego komponentu, że mogę używać, mimo że składnik a to funkcje są takie same. Rozwiązania te nie wydają się dobrym rozwiązaniem, ponieważ będzie dużo nadmiarowego kodu.

  • Twórz akcje o wystarczających parametrach, aby odróżnić każdą z nich w reduktorze i w ten sposób zmienić tylko wybraną część stanu.

Poszedłem do przodu z drugą opcją. złożyć

Akcje dla składnika CheckBox:

import {createAction} from 'redux-actions'; 

/****** Actions ******/ 
export const CHANGE_CHECKBOX_STATE = "CHANGE_CHECKBOX_STATE"; 

/****** Action creators ******/ 
export const changeCheckboxState = createAction(CHANGE_CHECKBOX_STATE, (block, name, state) => { 
    return { 
    block, 
    name, 
    state: { 
     checked: state, 
    } 
    }; 
}); 

Redukcje plik dla składnika CheckBox:

import {handleActions} from 'redux-actions'; 

import {CHANGE_CHECKBOX_STATE} from './CheckBox.actions'; 

export const checkBoxComponent = handleActions({ 
    CHANGE_CHECKBOX_STATE: (state, action) => ({ 
    [action.payload.block]: { 
     [action.payload.name]: action.payload.state 
    } 
    }) 
}, {}); 

używam block aby określić stronę, name, aby podać nazwę konkretnego składnika (np. płeć) i stan jako i obiekt z nowym stanem.

Ale to rozwiązanie ma też pewne problemy:

  • Nie można określić stan początkowy każdego składnika, ponieważ klucze stanu są dynamiczne.
  • Skomplikowuje strukturę magazynu z wieloma stanami zagnieżdżonymi.
  • Agreguje dane według komponentu, a nie według formy, co komplikuje debugowanie i jest logicznie niepoprawne.

Nie mam wystarczającego doświadczenia z Redux i React, aby wymyślić lepsze rozwiązanie tego problemu. Ale wydaje mi się, że jestem brakuje czegoś ważnego o relacji React-Redux i to rodzi pewne pytania:

  • jest to dobry pomysł, aby zachować stan tego komponentów wielokrotnego użytku do sklepu Redux?

  • Czy źle się ze sobą wiążę Reaguj na komponenty za pomocą akcji Redux i reduktorów?

+0

ja nie rozumiem, dlaczego należałoby zachować stan kontrolny w ten sposób? Czy nie ma rzeczywistych danych? I te dane nie dają żadnych bzdur na temat tego, jak są renderowane? Wygląda na to, że mnie rozrywasz. –

+0

@ChrisMartin Próbowałem wyjaśnić tutaj, jak doszedłem do tej decyzji, ale powiedziałem również, że wiem, że robię coś złego, po prostu nie widzę, co to jest. Czy możesz mi wytłumaczyć, jak zaprojektowałbyś to? Może w ten sposób zobaczę, co jest nie tak z moim podejściem. Dziękuję za odpowiedź! – Roc

+0

Proszę obejrzeć te filmy: [https://egghead.io/series/getting-started-with-redux] (https://egghead.io/series/getting-started-with-redux) ... – Mike

Odpowiedz

4

Podstawowym błędem jest to, że masz 0 głupich komponentów.Podstawowe elementy sterujące, takie jak pola wyboru, powinny być niemymi komponentami wykorzystującymi tylko rekwizyty, a ich rodzic ma obowiązek wybrać i zaktualizować odpowiedni element stanu dla określonego pola wyboru.

+0

Nono , wszystkie są głupie komponenty, działania i reduktory są tylko dla składników macierzystych i przechowywać do użycia. – Roc

8

Nie opisuj reduktorów Redux (ogólny stan aplikacji) pod względem składników zużywających ten stan. Śledź to w inny sposób, opisując swój stan aplikacji w sposób opisowy, a następnie "głupie" komponenty zużywają ten opisowy stan.

Zamiast śledzić "Stan tego pola wyboru dla formularza związanego z foo", śledzić "tę wartość boolowską foo", a następnie pole wyboru spożywa ten stan.

przenoszone przez przykład do wyboru:

const initialState = { 
    someFooItem: { isCertainType: false } 
}; 

export function foos(state = initialState, action) { 
    switch(action.type){ 
     case(UPDATE_FOO_VALUE): 
      return { 
       ...state, 
       [action.payload.id]: { 
        isCertainType: action.payload.isCertainType 
       } 
      } 
    } 
} 

Przykładem wyboru spożywającej sklep

class CheckBox extends React.Component { 
    render() { 
     return <input type="checkbox" checked={this.props.checked} /> 
    } 
} 

Komponent nadrzędny

class ParentComponent extends React.Component { 
    render() { 
     return <CheckBox checked={this.foo.isCertainType} /> 
    } 
} 
+0

Jeśli dobrze cię zrozumiałem, twoje rozwiązanie nie rozwiązuje problemu tylko dlatego, że generalizujesz formularz, w którym pole wyboru będzie, ale jeśli mam trzy pola wyboru, każdy z innymi zainteresowaniami (np. Sport, Przygoda, Gotowanie) dla każdego z nich z nich będę musiał stworzyć inny reduktor, nawet jeśli funkcjonalność jest taka sama. – Roc

+1

Sport, przygoda, gotowanie będą "zainteresowaniami", więc możesz mieć reduktor typu '{interests: {cooking: true, sports: false, adventure: false}}' i użyć go do przedstawienia widoku. – Danita

Powiązane problemy