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

125

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

Мне любопытно, почему это так, в примере приложения TODO в документации redux метод mapDispatchToProps настраивается таким же образом. Когда я console.log (отправка) внутри функции, он говорит, что отправка - это объект типа. Я мог бы продолжать использовать диспетчеризацию таким образом, но мне было бы лучше знать, почему это происходит, прежде чем я продолжу работу с redux. Я использую 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

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

пятнать
источник
У меня была эта проблема, и это помогло мне ее решить
Alex W

Ответы:

250

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

export default connect(null, mapDispatchToProps)(Start)

inostia
источник
4
Это то, что я искал. Теперь я знаю, хочу ли я просто выполнить какие-то действия.
Император Краузер
Это именно то, что я искал. Спасибо за отличное решение. Что, если нам не нужно использовать mapDispatchToProps ни в одном из наших компонентов? Мы должны действовать таким же образом в этом сценарии?
Арун Рамачандран
1
Если вам это не нужно mapDispatchToProps, просто не добавляйте этот аргумент к connect:connect(mapStateToProps)(MyComponent)
inostia
107

Вам просто не хватает первого аргумента 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)
Brandon
источник
3
обязательно ли использовать этот метод? Этот метод просто улавливает состояние, а что, если нам этот метод не нужен?
Muneem Habib
6
@MuneemHabib см. Ответ inostia о том, как не предоставлять этот метод, если он вам не нужен
Брэндон
22

использование

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

вместо того

const StartContainer = connect(mapDispatchToProps)(Start)
Энн
источник
6

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

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

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

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

Сейчас это звучит очевидно, но может кому-то помочь.

Амит Миттал
источник
3

Мне нужен был пример использования, 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);
Amio.io
источник
3

вопрос

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

Арность connectвопросов:connect(mapStateToProps, mapDispatchToProps)

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

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

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

Connected компонент получает dispatchпо умолчанию, когда нет mapDispatchПРЕДОСТАВЛЯЕТСЯ

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

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

Вышеупомянутый ответ объясняет, почему компонент так себя ведет. Тем не менее, это обычная практика, когда вы просто передаете свой создатель действий, используя 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)
wgao19
источник
0

Когда вы не указываете 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

Серж Николаев
источник
0

Я использую вот так ... его легко понять, первый аргумент - это 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);
Абдул Моиз
источник
если у вас нет первого аргумента, просто передайте null / undefined, а затем второй аргумент ..
Абдул Моиз
0

Иногда эта ошибка также возникает, когда вы изменяете порядок функции компонента при переходе на соединение.

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

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

Правильный заказ:

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
Codiee
источник
0

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

Эта ошибка возникает при использовании 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отсутствовала в коде ошибки

я Бэтмен
источник
0

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

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

Если мы не хотим получать состояние из redux, мы устанавливаем null вместо mapStateToProps.

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

Сачин Меткари
источник