2016-08-16 26 views
1

Я новичок в Redux и пытаюсь выяснить масштабный способ настройки моей папки/структуры файлов.Шаблон для управления несколькими редукторами внутри модуля [Redux]

Допустим, мы имеем файловую структуру, которая выглядит следующим образом:

корневые/модули/Todos/редукторы

В корне проекта живет файл «rootReducer.js» который использует 'combineReducers() для создания реализации верхнего уровня государственного дерева:

[rootReducer.js] 

import { combineReducers } from 'redux'; 

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

export default combineReducers({ 
    todos: todos 
}); 

Внутри папки «рЕДУКТОРЫ» для каждого модуля существует несколько редукторы:

[root/modules/Todos/reducers] 

>index.js 
>Todos__addItem 
>Todos__removeItem 

импортирует файл «index.js» все из переходников для этого модуля и экспортирует один объект:

[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 
}); 

Является ли это правильное использование «combineReducers()»?

Этот шаблон имеет смысл при разработке крупномасштабного приложения?

Какие (если есть) потенциальные ловушки, которые приходят вместе с этим рисунком?

Спасибо!

+0

https://github.com/suin/redux-multiple-reducers-example. ПРИМЕР!!!!!! – zloctb

ответ

2

Это определенно неправильное использование combineReducers. combineReducers используется для делегирования управления определенным срезом состояния для данной функции. В вашем примере на самом деле создаются срезы состояния с именем addItem и removeItem, когда то, что вы действительно хотите сделать, - это обновление того же todos фрагмента состояния, используя эти функции по-разному в зависимости от того, какое действие было отправлено.

Я нахожусь в процессе написания нового раздела для документов Redux на тему «Структурирование редукторов». Вы можете прочитать текущий проект WIP - некоторые из них могут помочь. Проект доступен по телефону https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md. Некоторые из примеров должны иметь отношение к вашему вопросу.

+0

Я ценю ответ и работу, которые вы сделали с вашими работами! Что касается инструкции «export todos» в «index.js», знаете ли вы, как я могу реорганизовать это, чтобы достичь того, что я ищу?У меня возникли проблемы с правильной настройкой! Должен ли я экспортировать коллекцию субредукторов как функцию или просто простой объект? – Celestriel

+0

Обработка 'todo' была бы там, где вы увидите типичный оператор switch или таблицу поиска для различных случаев обновления. См. Http://redux.js.org/docs/recipes/ReducingBoilerplate.html#generating-reducers для соответствующего примера. Кроме того, в случае, если вы еще их не видели, у Дэна есть две отличные серии видеороликов, где он демонстрирует несколько подходов к редуктору: https://egghead.io/series/getting-started-with-redux и https: // egghead.io/series/building-react-applications-with-idiomatic-redux. – markerikson

0

пример из 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> 
    ); 
    } 

счетчика1 зрения

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 вид

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

import Counter1 from "../components/Counter1"; 
import Counter2 from "../components/Counter2"; 

class CounterApp extends React.Component{ 
    render() { 
    return (
     <div> 
     <Counter1/> 
     <Counter2/> 
     </div> 
    ); 
    } 
} 

редуктор

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; 
    } 
}