'dispatch' не является функцией, когда аргумент mapToDispatchToProps() в Redux

Я начинаю javascript/redux/реагировать, создавая небольшое приложение с сокращением, реагирует-редукцией и реагирую. По какой-то причине при использовании функции mapDispatchToProps в тандеме с подключением (привязка редукция-редукция) я получаю TypeError, указывающий, что отправка не является функцией, когда я пытаюсь выполнить полученную подсказку. Однако, когда я вызываю диспетчер в качестве опоры (см. Функцию setAddr в предоставленном коде), он работает.

Мне интересно, почему это так, в примере приложения TODO в документах redux метод mapDispatchToProps настроен таким же образом. Когда я console.log(отправка) внутри функции, она говорит, что отправка - это объект типа. Я мог бы продолжать использовать рассылку таким образом, но я бы чувствовал себя лучше, зная, почему это происходит, прежде чем я продолжу дальнейшее сокращение. Я использую webpack с загрузчиками babel для компиляции.

Мой код:

import React, { PropTypes, Component } from 'react';
import { connect } from 'react-redux';
import { setAddresses } from '../actions.js';
import GeoCode from './geoCode.js';
import FlatButton from 'material-ui/lib/flat-button';

const Start = React.createClass({
    propTypes: {
        onSubmit: PropTypes.func.isRequired
    },

    setAddr: function(){
        this.props.dispatch(
            setAddresses({
                pickup: this.refs.pickup.state.address,
                dropoff: this.refs.dropoff.state.address
            })
        )   

    },

    render: function() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-6">
                        <GeoCode ref='pickup' />
                    </div>
                    <div className="col-xs-6">
                        <GeoCode ref='dropoff' />
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-6">
                        <FlatButton 
                            label='Does Not Work'
                            onClick={this.props.onSubmit({
                                pickup: this.refs.pickup.state.address,
                                dropoff: this.refs.dropoff.state.address
                            })} 
                            />
                    </div>
                    <div className="col-xs-6">
                        <FlatButton 
                            label='Works'
                            onClick={this.setAddr} 
                            />
                    </div>
                </div>
            </div>
        );
    }
})

const mapDispatchToProps = (dispatch) => {
    return {
        onSubmit: (data) => {
            dispatch(setAddresses(data))
        }
    }
}

const StartContainer = connect(mapDispatchToProps)(Start)

export default StartContainer

Приветствия.

Ответ 1

Если вы хотите использовать mapDispatchToProps без mapStateToProps, просто используйте null для первого аргумента.

export default connect(null, mapDispatchToProps)(Start)

Ответ 2

Вам просто не хватает первого аргумента connect, который является методом mapStateToProps. Выдержка из приложения Redux todo:

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

Ответ 3

Используйте

const StartContainer = connect(null, mapDispatchToProps)(Start) 

вместо

const StartContainer = connect(mapDispatchToProps)(Start)

Ответ 4

Я решил это, заменив аргументы, я использовал

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

что неверно. mapStateToProps должен быть первым аргументом:

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

Теперь это звучит очевидно, но может помочь кому-то.

Ответ 5

Мне нужен пример с помощью React.Component, поэтому я отправляю его:

import React from 'react';
import * as Redux from 'react-redux';

class NavigationHeader extends React.Component {

}

const mapStateToProps = function (store) {
    console.log(`mapStateToProps ${store}`);
    return {
        navigation: store.navigation
    };
};

export default Redux.connect(mapStateToProps)(NavigationHeader);

Ответ 6

вопрос

Вот несколько вещей, на которые следует обратить внимание, чтобы понять поведение подключенного компонента в вашем коде:

Артерия connect имеет значение: connect(mapStateToProps, mapDispatchToProps)

Вызовы React-Redux connect с первым аргументом mapStateToProps и вторым аргументом mapDispatchToProps.

Поэтому, несмотря на то, что вы передали в свой mapDispatchToProps, React-Redux фактически обрабатывает это как mapState потому что это первый аргумент. Вы по-прежнему получаете onSubmit функцию onSubmit в своем компоненте, потому что возвращение mapState объединяется с реквизитами вашего компонента. Но это не то, как mapDispatch должен быть введен.

Вы можете использовать mapDispatch без определения mapState. Передайте значение null вместо mapState и ваш компонент не будет подвергаться изменениям магазина.

Подключенный компонент получает dispatch по умолчанию, если не mapDispatch

Кроме того, ваш компонент получает dispatch поскольку он получил значение null для своей второй позиции для mapDispatch. Если вы правильно передадите mapDispatch, ваш компонент не получит dispatch.

Обычная практика

Приведенный выше ответ отвечает, почему компонент вел себя таким образом. mapStateToProps, это обычная практика, когда вы просто передаете свой создатель действия, используя mapStateToProps объекта mapStateToProps. И назовите это в вашем компоненте onSubmit То есть:

import { setAddresses } from '../actions.js'

const Start = (props) => {
  // ... omitted
  return <div>
    {/** omitted */}
    <FlatButton 
       label='Does Not Work'
       onClick={this.props.setAddresses({
         pickup: this.refs.pickup.state.address,
         dropoff: this.refs.dropoff.state.address
       })} 
    />
  </div>
};

const mapStateToProps = { setAddresses };
export default connect(null, mapDispatchToProps)(Start)

Ответ 7

Когда вы не предоставляете mapDispatchToProps в качестве второго аргумента, например:

export default connect(mapStateToProps)(Checkbox)

тогда вы автоматически получаете отправку для компонентов, поэтому вы можете просто:

class SomeComp extends React.Component {
  constructor(props, context) {
    super(props, context);
  }
  componentDidMount() {
    this.props.dispatch(ACTION GOES HERE);
  }
....

без каких-либо mapDispatchToProps

Ответ 8

я использую, как это.. его легко понять, первый аргумент mapStateToProps и второй аргумент mapDispatchToProps в конце соединиться с функцией/классом.

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

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

Ответ 9

Иногда эта ошибка также возникает при изменении порядка функции компонента при передаче для подключения.

Неверный заказ:

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

Правильный порядок:

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

Ответ 10

Подводный камень, в который могут попасть некоторые, рассматривается в этом вопросе, но не рассматривается в ответах, поскольку он немного отличается по структуре кода, но возвращает точно такую же ошибку.

Эта ошибка возникает при использовании bindActionCreators и без передачи функции dispatch

Код ошибки

import someComponent from './someComponent'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import { someAction } from '../../../actions/someAction'

const mapStatToProps = (state) => {
    const { someState } = state.someState

    return {
        someState
    }
};

const mapDispatchToProps = (dispatch) => {
    return bindActionCreators({
        someAction
    });
};

export default connect(mapStatToProps, mapDispatchToProps)(someComponent)

Фиксированный код

import someComponent from './someComponent'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import { someAction } from '../../../actions/someAction'

const mapStatToProps = (state) => {
    const { someState } = state.someState

    return {
        someState
    }
};

const mapDispatchToProps = (dispatch) => {
    return bindActionCreators({
        someAction
    }, dispatch);
};

export default connect(mapStatToProps, mapDispatchToProps)(someComponent)

Функция dispatch отсутствует в коде ошибки

Ответ 11

React-redux 'connect' функция принимает два аргумента: первый - это mapStateToProps, а второй - проверка mapDispatchToProps, например, ниже.

export default connect(mapStateToProps, mapDispatchToProps)(Index); '

Если мы не хотим извлекать состояние из избыточного числа, тогда мы устанавливаем нуль вместо mapStateToProps.

export default connect(null, mapDispatchToProps)(Index);