it-roy-ru.com

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

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

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

Мой код:

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

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

88
sully

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

export default connect(null, mapDispatchToProps)(Start)

118
inostia

Вы просто пропускаете первый аргумент 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)
100
Brandon

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

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

вместо 

const StartContainer = connect(mapDispatchToProps)(Start)
17
Ann

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

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

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

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

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

4
Amit Mittal

Мне нужен пример с использованием 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
Amio.io

Вопрос

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

Arity of connect Вопросы: connect(mapStateToProps, mapDispatchToProps)

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

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

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

Подключенный компонент получает 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)
2
wgao19

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

Неправильный заказ:

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

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

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

Когда вы не предоставляете 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
Serge Nikolaev

я использую как это .. его легко понять, первый аргумент - 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);
0
Abdul Moiz