Creazione di azioni generiche in redux

4

Mi chiedo se c'è qualcosa di sbagliato nella creazione di azioni generiche in redux che cambiano dinamicamente le diverse proprietà nell'archivio, in modo da poter ridurre il codice boilerplate.

Ad esempio:

//GenericActions.js

function replace(data, property) {
  return { 
        actionType: GenericConstants.ADD
        data,
        property
    }
}
export default replace;

//GenericReducer.js

function genericReducer(state, action) {
    switch(action.actionType) {
        case GenericConstants.ADD:
            let change = {};
            let change[action.property] = [ ...state[action.property], action.data];
            return Object.assign({}, state, change);
    }
}
export default genericReducer;
    
posta Mr. MonoChrome 14.06.2016 - 17:50
fonte

1 risposta

1

So che è un po 'vecchio, ma di recente sono passato a un modello simile a mano a mano che la mia applicazione è cresciuta. Poiché l'interfaccia utente e i requisiti dei dati diventano più complessi, ho scoperto che abbiamo finito con un elenco non modificabile di tipi di azione, molti dei quali stanno facendo esattamente la stessa cosa su bit di dati leggermente diversi. Nella mia nuova struttura dell'interfaccia utente abbiamo qualcosa di simile (non questi valori esatti, ma lo stesso stile). Per prima cosa definiamo le costanti che costituiscono l'interfaccia utente delle applicazioni:

/* ui-constants.js */

export const FORM = 'FORM';
export const NAV = 'NAV';
export const DLG_ALERT = 'DLG_ALERT';
export const DLG_ERROR = 'DLG_ERROR';

export const UI_KEYS = {
    VISIBLE: 'visible',
    TITLE: 'title',
    MESSAGE: 'message'
    ENABLED: 'enabled'
};

Quindi il nostro stato di interfaccia utente iniziale è costituito da queste costanti.

/* state-ui.js */

const UIState = {
    [UI_KEYS.VISIBLE]: {
        [FORM]: false,
        [NAV]: false,
        [DLG_ALERT]: false,
        [DLG_ERROR]: false
    },
    [UI_KEYS.ENABLED]: {
        [FORM]: false,
        [NAV]: false,
        [DLG_ALERT]: false,
        [DLG_ERROR]: false
    },
    [UI_KEYS.MESSAGE]: {
        [FORM]: '',
        [DLG_ALERT]: '',
        [DLG_ERROR]: ''
    },
    [UI_KEYS.TITLE]: {
        [DLG_ALERT]: '',
        [DLG_ERROR]: ''
    }
};

Questo ci consente quindi di utilizzare azioni generiche per cambiare parti dell'interfaccia utente in base alle chiavi dell'interfaccia utente. Quindi, per esempio, abbiamo azioni come questa

{
    type: UI_TOGGLE, // constant defined elsewhere
    ui: DLG_ALERT,
    key: UI_KEYS.ENABLED
}

Quindi il riduttore UI lo gestisce in questo modo

switch(type) {
    case UI_TOGGLE:
        newState[action.key][action.ui] = !state[action.key][action.ui];
    ...
}

Facciamo una cosa simile per i nostri dati dell'applicazione poiché è in gran parte CRUD (?) di tali dati e funziona in modo simile.

Il lato negativo che posso vedere, credo, è che interrompe il modello di un'azione ripetuta che ha lo stesso identico effetto ogni volta che viene chiamato, poiché UI_TOGGLE può commutare qualsiasi numero all'interno dell'interfaccia utente. Tuttavia, penso che questo si applichi solo se consideri che l'azione stessa sia definita dal suo tipo e solo dal suo tipo. Abbiamo trovato una singola stringa costante per essere molto limitata nella sua capacità di descrivere un'azione, quindi invece la "firma" delle azioni, se vuoi, è considerata una somma di tutte le sue parti.

Credo che la proprietà type in questo stile sia più fedele al suo significato, nel senso che stiamo semplicemente definendo il "metodo" o la "descrizione" dell'azione che sta per avvenire, piuttosto che contenere ulteriormente le parti dello stato che influenzerà.

prendi l'esempio SET_VISIBLITY_FILTER dai documenti di Redux. Il "tipo" dell'azione non sta solo descrivendo cosa sta per accadere (in questo caso, impostando un valore di filtro), ma sta anche descrivendo che è il filtro di visibilità che sarà interessato. Se vuoi anche avere un filtro evidenziato, ad esempio avrai bisogno di due azioni:

{
    type: SET_VISIBILITY_FILTER,
    filter: SHOW_COMPLETED
},
{
    type: SET_HIGHLIGHTED_FILTER,
    filter: SHOW_INCOMPLETE
}

Con un'azione generica, questa può essere ridotta a una singola azione con una singola funzione di riduttore

{
    type: SET_FILTER,
    filter: VISIBLITY,
    value: SHOW_COMPLETED
}

Questo modo di fare le cose richiede di pensare di più al tuo albero di stato, e di come tutte le parti saranno rappresentate e modificate. Ma penso che, a lungo termine, questo sia in realtà una buona cosa, in quanto ti costringe a costruire un robusto albero di stato, piuttosto che semplicemente scaricare lo stato in nomi di variabili diversi quando ti vengono in mente.

Quindi, sì, sì, penso che questo sia un modo accettabile di fare le cose, e tu hai ragione nel dire che riduce il codice di caldaia. Mentre aggiunge una quantità extra di codice alle tue azioni, rimuove una tonnellata di codice riduttore. Dal momento che il riduttore è l'unico luogo in cui si verificherà lo stato, ritengo che in realtà renda più facile trovare problemi.

    
risposta data 12.09.2016 - 06:12
fonte

Leggi altre domande sui tag