Ich bin ein Javascript/Redux/Reactor-Anfänger, der eine kleine Anwendung mit Redux, React-Redux und React erstellt. Aus irgendeinem Grund, wenn ich die Funktion mapDispatchToProps in Verbindung mit connect (react-redux-Bindung) verwende, erhalte ich einen TypeError, der angibt, dass dispatch keine Funktion ist, wenn ich die resultierende Eigenschaft ausführen möchte. Wenn ich dispatch als Requisite jedoch anrufe (siehe setAddr-Funktion im bereitgestellten Code), funktioniert es.
Ich bin neugierig, warum dies so ist. In der Beispiel-TODO-App in den redux-Dokumenten wird die mapDispatchToProps-Methode auf dieselbe Weise eingerichtet. Wenn ich innerhalb der Funktion console.log (dispatch) verweise, heißt es, dass dispatch vom Typ object ist. Ich könnte Dispatch auf diese Weise weiterverwenden, aber ich würde besser wissen, warum dies geschieht, bevor ich mit redux fortfahre. Ich verwende Webpack mit Babel-Loadern zum Kompilieren.
Mein Code:
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
Prost.
Das erste Argument fehlt nur bei connect
, der mapStateToProps
-Methode. Auszug aus der Redux-todo-App:
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)
Wenn Sie mapDispatchToProps
ohne mapStateToProps
verwenden möchten, verwenden Sie null
für das erste Argument.
export default connect(null, mapDispatchToProps)(Start)
Benutzen
const StartContainer = connect(null, mapDispatchToProps)(Start)
anstatt
const StartContainer = connect(mapDispatchToProps)(Start)
Ich löste es, indem ich die Argumente austauschte, die ich verwendete
export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)
was falsch ist. Die mapStateToProps
muss das erste Argument sein:
export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)
Das hört sich jetzt offensichtlich an, könnte aber jemandem helfen.
Ich brauchte ein Beispiel mit React.Component
, also poste ich es:
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);
Hier sind einige Dinge, die Sie beachten sollten, um das Verhalten der verbundenen Komponente in Ihrem Code zu verstehen:
Die Vielseitigkeit von connect
-Angelegenheiten: connect(mapStateToProps, mapDispatchToProps)
React-Redux ruft connect
mit dem ersten Argument mapStateToProps
und dem zweiten Argument mapDispatchToProps
auf.
Obwohl Sie Ihre mapDispatchToProps
übergeben haben, behandelt React-Redux dies jedoch als mapState
, da es das erste Argument ist. Sie erhalten weiterhin die injizierte onSubmit
-Funktion in Ihrer Komponente, da die Rückgabe von mapState
in die Requisiten Ihrer Komponente eingebunden wird. Aber so soll nicht mapDispatch
injiziert werden.
Sie können mapDispatch
verwenden, ohne mapState
zu definieren. Übergeben Sie null
anstelle von mapState
, und Ihre Komponente wird nicht gespeichert.
Die verbundene Komponente erhält standardmäßig dispatch
, wenn keine mapDispatch
bereitgestellt wird
Außerdem erhält Ihre Komponente dispatch
, da sie null
für ihre zweite Position für mapDispatch
erhalten hat. Wenn Sie mapDispatch
richtig übergeben, erhält Ihre Komponente dispatch
nicht.
Die obigen Antworten geben an, warum sich die Komponente so verhalten hat. Es ist jedoch allgemein üblich, dass Sie Ihren Aktionsersteller einfach mit der __mapStateToProps
-Objektkürzel übergeben. Und nennen Sie das in Ihrer Komponente onSubmit
Das heißt:
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)
Manchmal tritt dieser Fehler auch auf, wenn Sie die Reihenfolge der Komponentenfunktionen während der Übergabe ändern, um eine Verbindung herzustellen.
Falsche Reihenfolge:
export default connect(mapDispatchToProps, mapStateToProps)(TodoList);
Korrekten Reihenfolge:
export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
Eine Falle, in die einige möglicherweise geraten, wird von dieser Frage abgedeckt, in den Antworten jedoch nicht angesprochen, da sie sich in der Codestruktur geringfügig unterscheidet, aber genau denselben Fehler zurückgibt.
Dieser Fehler tritt auf, wenn bindActionCreators
verwendet wird und die Funktion dispatch
nicht übergeben wird
Fehlercode
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)
fester Code
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)
Die Funktion dispatch
fehlte im Fehlercode
Wenn Sie als zweites Argument nicht mapDispatchToProps
angeben, geben Sie Folgendes ein:
export default connect(mapStateToProps)(Checkbox)
dann erhalten Sie automatisch den Versand zu den Requisiten der Komponente. Sie können also:
class SomeComp extends React.Component {
constructor(props, context) {
super(props, context);
}
componentDidMount() {
this.props.dispatch(ACTION GOES HERE);
}
....
ohne mapDispatchToProps
Die 'Connect'-Funktion von React-Redux akzeptiert zwei Argumente: erstens mapStateToProps und zweitens mapDispatchToProps.
export default connect(mapStateToProps, mapDispatchToProps)(Index);
`
Wenn wir den Status nicht von Redux abrufen möchten, setzen wir null anstelle von mapStateToProps.
export default connect(null, mapDispatchToProps)(Index);
ich benutze so .. das erste Argument ist leicht zu verstehen ist mapStateToProps und das zweite Argument ist MapDispatchToProps am Ende verbinden mit Funktion/Klasse.
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);