'dispatch' не є функцією, коли аргумент mapToDispatchToProps () в Redux


124

Я Javascript / redux / реагую новачок, будуючи невелику програму з redux, react-redux, & react. Чомусь при використанні функції mapDispatchToProps в тандемі з підключенням (реакція-скорочення прив'язки) я отримую TypeError, що вказує, що відправка не є функцією, коли я намагаюся виконати отриману опору. Коли я викликаю диспетчер як опору (див. Функцію setAddr у наданому коді), вона працює.

Мені цікаво, чому це відбувається, наприклад, у прикладі програми TODO у документах із скороченням mapDispatchToProps метод налаштовується так само. Коли я console.log (dispatch) всередині функції, він каже, що dispatch є об'єктом типу. Я міг би продовжувати використання диспетчера таким чином, але мені буде краще, знаючи, чому це відбувається, перш ніж продовжувати далі з редукцією. Я використовую webpack з навантажувачами для завантаження.

Мій код:

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

Відповіді:


249

Якщо ви хочете використовувати 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 про те, як не надавати цей метод, якщо він вам не потрібен
Брендон

21

Використовуйте

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

без будь-якої картиDispatchToProps


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, а потім другий аргумент ..
Abdul Moiz

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.