'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)


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)

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);

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)

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);

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);

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.