2016-08-16 6 views
1

Ich bin neu in Redux und versuche, eine skalierbare Möglichkeit zu finden, meine Projektordner/Dateistruktur einzurichten.Muster zum Verwalten mehrerer Reduzierungen innerhalb eines Moduls [Redux]

Lets sagen, dass wir eine Dateistruktur haben, die wie folgt aussieht:

root/modules/Todos/Reduzierungen

In der Wurzel des Projekts ein 'rootReducer.js' Datei lebt welche nutzt ‚combineReducers()‘ zu schaffen, eine Top-Level-Implementierung des Zustandsbaums:

[rootReducer.js] 

import { combineReducers } from 'redux'; 

import todos from './modules/Todos/reducers/index.js'; 

export default combineReducers({ 
    todos: todos 
}); 

Innerhalb der ‚Reduzierer‘ Ordner für jedes Modul gibt es mehr Reduzierungen:

[root/modules/Todos/reducers] 

>index.js 
>Todos__addItem 
>Todos__removeItem 

Die für dieses Modul alle der Reduzierungen Datei Importe ‚index.js‘ und exportiert ein einzelnes Objekt:

[index.js] 

import { combineReducers } from 'redux'; 

import addItem from './Todos__addItem.js'; 
import removeItem from './Todos__removeItem.js'; 

export default const todos = combineReducers({ 
    addItem: addItem, 
    removeItem: removeItem 
}); 

Ist dies die richtige Verwendung von ‚combineReducers()‘?

Macht dieses Muster Sinn, wenn Sie eine groß angelegte Anwendung entwickeln?

Was sind (wenn überhaupt) mögliche Fallstricke, die mit diesem Muster einhergehen?

Danke!

+0

https://github.com/suin/redux-multiple-reducers-example. BEISPIEL!!!!!! – zloctb

Antwort

2

Es ist definitiv nicht die korrekte Verwendung von combineReducers. combineReducers wird verwendet, um die Verwaltung eines bestimmten Statusbereichs an eine bestimmte Funktion zu delegieren. Ihr Beispiel würde tatsächlich Zustandsschichten mit den Namen addItem und removeItem erstellen, wenn Sie das gleiche todos Staatsgebiet mit diesen Funktionen auf verschiedene Arten aktualisieren möchten, je nachdem, welche Aktion ausgelöst wurde.

Ich bin gerade dabei, einen neuen Abschnitt für die Redux-Dokumente zum Thema "Strukturierungsreduzierer" zu schreiben. Vielleicht möchten Sie den aktuellen WIP-Entwurf durchlesen - einige davon könnten helfen. Der Entwurf ist verfügbar unter https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md. Einige der Beispiele sollten für Ihre Frage relevant sein.

+0

Ich schätze die Antwort und die Arbeit, die Sie mit Ihren Schriften getan haben! In Bezug auf die "Export Todos" Aussage in "index.js", wissen Sie, wie ich das umgestalten könnte, um das zu erreichen, wonach ich suche?Ich habe Probleme, den richtigen Weg zu finden, um es umzusetzen! Sollte ich die Sammlung von Unterreduzierern als eine Funktion oder nur ein einfaches Objekt exportieren? – Celestriel

+0

Die 'todo'-Behandlung wäre, wo Sie die typische switch-Anweisung oder Lookup-Tabelle für die verschiedenen Update-Fälle sehen würden. Ein relevantes Beispiel finden Sie unter http://redux.js.org/docs/recipes/ReducingBoilerplate.html#generating-reducers. Falls du sie noch nicht gesehen hast, hat Dan zwei großartige Video-Tutorial-Serien, in denen er eine Reihe von Reduktionsansätzen vorführt: https://egghead.io/series/getting-started-with-redux und https: // egghead.io/series/building-react-applications-with-idiomatic-redux. – markerikson

0

Beispiel aus https://github.com/suin/redux-multiple-reducers-example

import {counter1, counter2 } from "../../reducers/index" 
import CounterApp from "../containers/CounterApp"; 


const rootReducer = combineReducers({ 
    one:counter1 , 
    two:counter2 
}); 

const store = createStore(rootReducer); 

class App extends React.Component{ 
    render() { 
    return (
     <Provider store={store}> 
      <CounterApp /> 
     </Provider> 
    ); 
    } 

Counter1 Ansicht

import * as counter1Actions from "../../actions/counter1Actions"; 

@connect(state => ({ 
    counter1: state.one 
})) 
export default class Counter1 extends React.Component{ 

    static propTypes = { 
    counter1: PropTypes.number.isRequired 
    } 

    componentDidMount() { 
    console.info("counter1 component did mount."); 
    } 

    onClick() { 
    console.info("counter1 button was clicked."); 
    const action = bindActionCreators(counter1Actions, this.props.dispatch); 
    action.increment(); 
    } 

    render() { 
    return (
     <div> 
     <h1>Counter 1</h1> 
     <button onClick={::this.onClick}>increment</button> 
     <div>Total: <span>{this.props.counter1}</span></div> 
     </div> 
    ); 
    } 
} 

Counter2 Ansicht

import * as counter2Actions from "../../actions/counter2Actions"; 

@connect(state => ({ 
    counter2: state.two 
})) 
export default class Counter2 extends React.Component { 
    static propTypes = { 
    counter2: PropTypes.number.isRequired 
    } 

    componentDidMount() { 
    console.info("counter2 component did mount."); 
    } 

    onClick() { 
    console.info("counter2 button was clicked."); 
    const action = bindActionCreators(counter2Actions, this.props.dispatch); 
    action.increment(); 
    } 

    render() { 
    return (
     <div> 
     <h1>Counter 2</h1> 
     <button onClick={::this.onClick}>increment</button> 
     <div>Total: <span>{this.props.counter2}</span></div> 
     </div> 
    ); 
    } 
} 

CounterApp

Minderer

export default function counter1(state = initialState, event) { 
    switch (event.type) { 
    case "COUNTER1_INCREMENTED": 
     console.info(`counter1 ack ${event.type}: event =`, event); 
     return state + 1; 
    default: 
     console.warn("counter1 ack unknown event: state =", state, "event =", event); 
     return state; 
    } 

export default function counter2(state: Object = initialState, event: Object): Object { 
    switch (event.type) { 
    case "COUNTER2_INCREMENTED": 
     console.info(`counter2 ack ${event.type}: event =`, event); 
     return state + 1; 
    default: 
     console.warn("counter2 ack unknown event: state =", state, "event =", event); 
     return state; 
    } 
} 
Verwandte Themen