2016-06-19 3 views
7

Я начал изучать реакцию-редукцию-неизменную пару дней назад, и я все еще довольно запутан в структурировании своего приложения. У меня есть php (symfony/laravel MVC background), поэтому нелегко понять мою концепцию javascript.React Redux Обязанности

1) У меня есть строки WrapperComponent:

export default function (props) { 
    const style = {position: "relative"}; 
    const lines = props.lines; 

    return (
     <div className='wrapper' style={style}> 
      {lines.map(line => (
       <Line key={line.get("id")} {...line.toObject()} /> 
      ))} 
      <Board /> 
     </div> 
    ); 
} 

2) То, что связано с WrapperContainer

import Wrapper from '../components/WrapperComponent'; 

export default connect(
    function mapStateToProps(state) { 
     return { 
      lines: state.lines.map(line => { 
       return line.set("board", { 
        width: state.board.get("width"), 
        height: state.board.get("height") 
       }); 
      }) 
     }; 
    }, 
    function mapDispatchToProps(dispatch) { 
     return {}; 
    } 
)(Wrapper); 

3) Тогда есть AddLine действие

export function addLine(type) { 
    return { 
     type: types.ADD_LINE, 
     payload: { 
      id: 3, top: 0, left: 0, diffX: 0, diffY: 0, type: type, board: { 
       width: 0, 
       height: 0 
      }, active: false 
     } 
    }; 
} 

4), что переговоры к LinesReducer

export default function LinesReducer(state = initialState, action) { 
    switch (action.type) { 
     case types.ADD_LINE: 
      return state.push(
       Map(action.payload) 
      ); 
     default: 
      return state; 
    } 
} 

5) Так что WrapperContainer может слушать изменения в состоянии и повторной визуализации линий

export default connect(
    function mapStateToProps(state) { 
     return { 
      lines: state.lines.map(line => { 
       return line.set("board", { 
        width: state.board.get("width"), 
        height: state.board.get("height") 
       }); 
      }) 
     }; 
    }, 
    function mapDispatchToProps(dispatch) { 
     return {}; 
    } 
)(Wrapper); 

Теперь мой вопрос:

Где я ставлю логику относительно действий AddLine?

Когда я создаю строку, я хочу установить ее идентификатор И я хочу установить его ширину так же, как ширина/высота другого компонента.

Я полагаю, что действия должны передавать только информацию из одного места в другое.

Тогда я думаю ... может быть, логика должна жить в LinesReducer. Но Lines редуктор не имеет доступа к глобальному состоянию приложения, поэтому я не знаю, какую ширину/высоту должна иметь новая строка.

Тогда есть WrapperContainer. Контейнер имеет информацию о состоянии всего приложения, поэтому представляется целесообразным прокручивать каждую строку и устанавливать идентификаторы, если они не установлены, и обновлять их ширину/высоту и другую информацию.

Но это не кажется мне правильным. Я думал об одном месте, которое собирало информацию о глобальном состоянии приложения, тогда оно добавило бы новую строку на основе этой информации, и ничто другое не коснется этой строки еще раз. За исключением другого действия.

Это правильный подход? Я действительно хочу изменить ширину/высоту линии, когда изменяется высота/ширина другого компонента, поэтому контейнер имеет для меня наибольший смысл.

EDIT:

Может быть:

1) установить ID в действии, когда линия на самом деле создается (я просто не знаю, сколько строк уже есть, так что я не знаю какой ID я должен установить)

2) установить ширину/высоту в контейнере, когда он передает линии в реквизиты (но если я в конечном итоге захочу отобразить линии в другом контейнере, мне придется дублировать код там, если я не создам некоторые «глобальная» функция, которая обрабатывает прохождение линий в реквизитах компонентов в контейнерах)

ответ

4

Вы должны сохранить свои редукторы как чистые функции.Это означает, что если вы вызываете их несколько раз с теми же аргументами, они будут иметь одинаковый ожидаемый результат, зависящий только от аргументов.

Сказанное, место, в которое вы должны положить этот тип логики, называется создатель действия, что на самом деле является вашей функцией addLine.

Создатели действий - это именно те функции, которые создают действия. Легко объединить термины «действие» и «создатель действия», поэтому сделайте все возможное, чтобы использовать правильный термин.

Создатели действий также могут быть асинхронными и иметь побочные эффекты.

Узнайте больше в docs

действий создателей могут быть осведомлены о текущем состоянии, добавив некоторые промежуточное программное обеспечение, как redux-thunk:

Redux Thunk промежуточного слоя позволяет писать создатели действий, которые возвращают функции вместо действия. Thunk может использоваться для задержки отправки действия или для отправки только в том случае, если выполняется определенное условие. Внутренняя функция получает методы хранилища dispatch и getState в качестве параметров.

+0

Прохладный спасибо. :) Но если я скажу 5 строк. Я хочу добавить 6-е. ActionCreator не знает, сколько строк в приложении. Как установить идентификатор новой строки? (я хочу, чтобы это было 6). Также я хочу установить ширину всех строк, подобных ширине другого компонента в моем приложении. Снова actionCreator не знает, какую информацию установить. – Michal

+0

Ваш создатель действия не делает, но вы можете использовать middlewares, чтобы ваши создатели действия знали из текущего состояния. Взгляните на [этот пример] (https://github.com/gaearon/redux-thunk#injecting-a-custom-argument), используя 'redux-thunk'. Создатель действия 'fetchUser' имеет доступ к' getState', из которого он должен знать о строках. –

+0

Я обновил ответ, чтобы включить эту информацию. –