Ответ 1
Если вы хотите использовать mapDispatchToProps
без mapStateToProps
, просто используйте null
для первого аргумента.
export default connect(null, mapDispatchToProps)(Start)
Я начинаю 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
Приветствия.
Если вы хотите использовать mapDispatchToProps
без mapStateToProps
, просто используйте null
для первого аргумента.
export default connect(null, mapDispatchToProps)(Start)
Вам просто не хватает первого аргумента 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)
Используйте
const StartContainer = connect(null, mapDispatchToProps)(Start)
вместо
const StartContainer = connect(mapDispatchToProps)(Start)
Я решил это, заменив аргументы, я использовал
export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)
что неверно. mapStateToProps
должен быть первым аргументом:
export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)
Теперь это звучит очевидно, но может помочь кому-то.
Мне нужен пример с помощью 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);
Вот несколько вещей, на которые следует обратить внимание, чтобы понять поведение подключенного компонента в вашем коде:
Артерия 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)
Когда вы не предоставляете 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
я использую, как это.. его легко понять, первый аргумент 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);
Иногда эта ошибка также возникает при изменении порядка функции компонента при передаче для подключения.
Неверный заказ:
export default connect(mapDispatchToProps, mapStateToProps)(TodoList);
Правильный порядок:
export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
Подводный камень, в который могут попасть некоторые, рассматривается в этом вопросе, но не рассматривается в ответах, поскольку он немного отличается по структуре кода, но возвращает точно такую же ошибку.
Эта ошибка возникает при использовании 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
отсутствует в коде ошибки
React-redux 'connect' функция принимает два аргумента: первый - это mapStateToProps, а второй - проверка mapDispatchToProps, например, ниже.
export default connect(mapStateToProps, mapDispatchToProps)(Index);
'
Если мы не хотим извлекать состояние из избыточного числа, тогда мы устанавливаем нуль вместо mapStateToProps.
export default connect(null, mapDispatchToProps)(Index);