React-Redux

Для полноценной работы приложения работающего на React, обычно подключают Redux.js - библиотека которая отвечает за слой Store архитектуры Flux. Для этого необходимо подключить библиотеку react-redux.js. Которая содержит компонент Provider и функцию connect.

Provider

ReactDOM.render(
 <Provider store = {store}>
  <MyComponent>
 </Provider>,
 document.getElementById('root')
);

Компонент Provider получает в качестве парамерта store. Он делает так что все его child могут получить доступ к store через this.context. Заметка Provider реализует передачу store посредством context-а. Мы можем и сами пробрасывать store без Provider и connect:

class Provider {
 static childContextTypes = {
  userActionCreators: PropTypes.object,
  userStore: PropTypes.object
 };

 getChildContext() {
  return {
  ...
  }
 }
}

class MyApp {
 static contextType = { userACtionCreators: PropTypes.object.isRequired };
}

Connect

class MyComponent extends React.Component{
 ...
}

mapStateToProps(state){
 return {
  user: state.user,
  page: state.page
 }
}

mapDispatchToProps(dispatch){
 return{
  pageAct : bindActionCreator(pageAction, dispatch)
 }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);

connect это функция высшего порядка - она оборачивает наш компонент (оберточный компонент). Предоставляя доступ и state через this.props.user и к действиям this.props.pageAct

метод mapStateToProps - функция которая подписывает наши компоненты на изменения состояния store. При каждом изменении это функция будет вызываться. Тут часто используют селекторы, функции которые получают необходимые данные из redux-хранилища, особенно полезно если хранилище у нас нормализованно, так же это отличное место для бизнес-логики (при условии что все данные хранятся локально, без вызова асинхронных запросов на сервер)

метод mapDispatchToProps - функция которая оборачивает actionCreator в dispatch (с помощью метода bindActionCreator. В результате компоненты могут вызывать action напрямую.

action: bindActionCreator(myAction, dispatch);
// можно переписать в 
action: (value) => dispatch(myAction(value));

connect также, для большей оптимизации, проверяет изменилось состояние или нет (не глубокое сравнение), и если только состояние изменилось вызывает mapStateToProps.

Третий (опциональный) агрумент - mergeProps. Выдержка из документации по данному параметру:

You may specify this function to select a slice of the state based on props, or to bind action creators to a particular variable from props.

Если дословно переводить - данная функция позволяет получить текущее состояние, либо передать событие путем привязки нашего экшена к переменной из props (применяется если например, при изменении состояния, возвращать ту или иную функцию).

Пример кода:

const mapStateToProps = (state) => {
 return state.play;
}

const mergeProps = (stateProps, dispatchProps) => {
 const {play} = stateProps;
 const {dispatch} = dispatchProps;
 const toggle = () => {
  dispatch(togglePlay());
  if (play != true) {
   this.playAction();
  } else {
   this.stopAction();
  }
 };

 return {
  play,
  togglePlay: () => toggle()
 }
}

const ButtonPlayComponentContainer = connect(mapStateToProps, null, mergeProsp)(ButtonPlayComponentView);

Тут все просто, в mergeProps прилетает текущее состояние stateProps и dispatchProps, которое даёт возможность отправить событие. Далее по коду делаем проверку состояния, результатом которой будет нужная функция и возвращаем объект с текущем state и событие, которое благополучно попадет в props нашего компонента.

Селекторы

data proccessing лучше выносить из компонента - чтобы не нагружать его (становится медленным) - размещать внутри mapStateToProps, а лучше внутри select-ов. т.к. при вызове любого action, будут вызваны абсолютно все mapStateToProps всех компонентов. И если там будет бизнес логика - то она будет вычисляться каждый раз. Для решения этой проблеммы нужно сравнивать пред результат с текущим, и хранить пред результат в самих селекторах при помощи техники memoriz-ации.

results matching ""

    No results matching ""