Connect

Функции mapStateToProps и mapDispatchToProps — основные аргументы connect(). Но у функции connect() есть ещё два аргумента, работа которых связана с основными. Третий и четвёртый аргументы используются редко, поэтому мы не будем подробнее на них останавливаться. Вы можете самостоятельно ознакомиться с ними в официальной документации.

А пока — закрепим использование функции connect() на примере:

import { connect } from 'react-redux';

function App(props) {
  // ...
   
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
          toggleTodo: () => dispatch(toggleTodo(ownProps.todoId)),
            addTodo: (text) => dispatch(addToDo(text)),
            changeLayout: () => dispatch({ type: 'CHANGE_LAYOUT' })
    };
};

const mapStateToProps = (store, ownProps) => {
  return { 
        todos: store.todos,
        theme: ownProps.theme ? ownProps.theme : store.appearance.theme,
        user: store.account.userData
    };
};

// Собираем всё вместе, передав два аргумента в connect
export default connect(mapStateToProps, mapDispatchToProps)(App);

В пакете redux есть вспомогательная функция — bindActionCreators(actionCreators, dispatch). Представим, что у нас есть такие экшены:


 // ./services/actions.js
 export function addTodo(text) {
   return {
     type: 'ADD_TODO',
     text
   }
 }
 
 export function removeTodo(id) {
   return {
     type: 'REMOVE_TODO',
     id
   }
 }

  

Вот так выглядит функция mapDispatchToProps без bindActionCreators:


 import { addTodo, removeToDo } from './services/actions';
 
 const mapDispatchToProps = dispatch => {
   return {
             addTodo: (text) => dispatch(addToDo(text)),
             removeToDo: (id) => dispatch(removeTodo(id))
     };
 };

  

А так — с использованием bindActionCreators:


 import * as TodoActionCreators from './services/actions'
 
 const mapDispatchToProps = dispatch => 
     bindActionCreators(TodoActionCreators, dispatch);

  

По сути, bindActionCreators — синтаксический сахар, который позволяет писать чуть меньше кода.

Но существует ещё более ёмкий способ передать функции отправки экшенов в пропсы компонента:


 import { addTodo, removeToDo } from './services/actions';
 
 const mapDispatchToProps = {
     addTodo,
     removeToDo
 }
 
  

Необязательно передавать оба аргумента в функцию connect(), но если оставить её совсем без аргументов, изменение данных в хранилище не будет вызывать повторный рендеринг, а в пропсах появится дополнительная функция — dispatch(). Эта функция доступна и в случае, если передан только первый аргумент — mapStateToProps. Вы сможете использовать dispatch() из пропсов напрямую в компоненте:


class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = { step: 'delivery' }    
    }

    componentDidMount() {
        this.props.dispatch({type: 'GET_DELIVERY_OPTIONS' });
    }

    render() {
        // ...
    }
}

export default connect()(App);
 

#react