'dispatch' n'est pas une fonction lorsque l'argument de mapToDispatchToProps () dans Redux

124

Je suis un débutant javascript / redux / react qui crée une petite application avec redux, react-redux et react. Pour une raison quelconque, lors de l'utilisation de la fonction mapDispatchToProps en tandem avec connect (liaison react-redux), je reçois un TypeError indiquant que la répartition n'est pas une fonction lorsque j'essaie d'exécuter le prop résultant. Cependant, quand j'appelle dispatch comme accessoire (voir la fonction setAddr dans le code fourni), cela fonctionne.

Je suis curieux de savoir pourquoi, dans l'exemple d'application TODO dans la documentation redux, la méthode mapDispatchToProps est configurée de la même manière. Quand je console.log (dispatch) à l'intérieur de la fonction, il dit que la répartition est un objet de type. Je pourrais continuer à utiliser la répartition de cette façon, mais je me sentirais mieux de savoir pourquoi cela se produit avant de continuer avec redux. J'utilise webpack avec des chargeurs babel pour compiler.

Mon 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

À votre santé.

souiller
la source
J'avais ce problème et cela m'a aidé à le résoudre
Alex W

Réponses:

249

Si vous souhaitez utiliser mapDispatchToPropssans mapStateToPropsutiliser juste nullpour le premier argument.

export default connect(null, mapDispatchToProps)(Start)

Inostia
la source
4
C'est ce que je cherchais. Maintenant, je sais si je veux simplement envoyer des actions.
Empereur Krauser
C'est exactement quelque chose que je cherchais. Merci pour la solution parfaite. Et si nous n'avons pas à utiliser mapDispatchToProps dans l'un de nos composants? Est-ce de la même manière que nous devons gérer ce scénario?
Arun Ramachandran
1
Si vous n'en avez pas besoin mapDispatchToProps, n'ajoutez pas cet argument à connect:connect(mapStateToProps)(MyComponent)
inostia
107

Il vous manque juste le premier argument de connect, qui est la mapStateToPropsméthode. Extrait de l'application 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)
Brandon
la source
3
est-il obligatoire d'utiliser cette méthode? Cette méthode capture juste l'état et si nous n'avons pas besoin de cette méthode?
Muneem Habib
6
@MuneemHabib voir la réponse d'inostia pour savoir comment ne pas fournir cette méthode si vous n'en avez pas besoin
Brandon
21

Utilisation

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

au lieu de

const StartContainer = connect(mapDispatchToProps)(Start)
Ann
la source
6

Je l'ai résolu en interchangeant les arguments, j'utilisais

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

ce qui est faux. Le mapStateToPropsdoit être le premier argument:

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

Cela semble évident maintenant, mais pourrait aider quelqu'un.

Amit Mittal
la source
3

J'avais besoin d'un exemple d'utilisation React.Componentalors je le poste:

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);
Amio.io
la source
3

Problème

Voici quelques points à noter pour comprendre le comportement du composant connecté dans votre code:

L'arité des connectchoses:connect(mapStateToProps, mapDispatchToProps)

React-Redux appelle connectavec le premier argument mapStateToPropset le second argument mapDispatchToProps.

Par conséquent, bien que vous ayez transmis votre mapDispatchToProps, React-Redux traite en fait cela comme mapStateparce que c'est le premier argument. Vous obtenez toujours la onSubmitfonction injectée dans votre composant car le retour de mapStateest fusionné dans les accessoires de votre composant. Mais ce n'est pas comme ça qu'on mapDispatchest censé être injecté.

Vous pouvez utiliser mapDispatchsans définir mapState. Passez à la nullplace de mapStateet votre composant ne sera pas soumis à des modifications de stockage.

Le composant connecté reçoit dispatchpar défaut, quand aucun mapDispatchn'est fourni

De plus, votre composant reçoit dispatchcar il a reçu nullsa deuxième position pour mapDispatch. Si vous passez correctement mapDispatch, votre composant ne recevra pas dispatch.

Pratique courante

Ce qui précède explique pourquoi le composant s'est comporté de cette façon. Cependant, il est courant que vous passiez simplement votre créateur d'action en utilisant mapStateToPropsla sténographie d'objet de. Et appelez cela dans votre composant onSubmitC'est -à -dire:

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)
wgao19
la source
0

Lorsque vous ne fournissez pas mapDispatchToPropsun deuxième argument, comme ceci:

export default connect(mapStateToProps)(Checkbox)

alors vous obtenez automatiquement l'envoi aux accessoires du composant, vous pouvez donc simplement:

class SomeComp extends React.Component {
  constructor(props, context) {
    super(props, context);
  }
  componentDidMount() {
    this.props.dispatch(ACTION GOES HERE);
  }
....

sans aucune mapDispatchToProps

Serge Nikolaev
la source
0

J'utilise comme ça .. son premier argument facile à comprendre est mapStateToProps et le second argument est mapDispatchToProps à la fin se connecter avec la fonction / classe.

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);
Abdul Moiz
la source
si vous n'avez pas le premier argument, passez simplement nul / non défini, puis le deuxième argument ..
Abdul Moiz
0

Parfois, cette erreur se produit également lorsque vous modifiez l'ordre de la fonction du composant lors de la connexion.

Ordre incorrect:

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

Bon ordre:

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

Un écueil dans lequel certains pourraient tomber est couvert par cette question mais n'est pas abordé dans les réponses car il est légèrement différent dans la structure du code mais renvoie exactement la même erreur.

Cette erreur se produit lors de l'utilisation bindActionCreatorset de la non-transmission de la dispatchfonction

Code d'erreur

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)

Code fixe

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)

La fonction dispatchétait manquante dans le code d'erreur

je suis Batman
la source
0

La fonction 'connect' de React-redux accepte deux arguments, le premier est mapStateToProps et le second est mapDispatchToProps, vérifiez ci-dessous ex.

export default connect(mapStateToProps, mapDispatchToProps)(Index); »

Si nous ne voulons pas récupérer l'état de redux, nous définissons null au lieu de mapStateToProps.

export default connect(null, mapDispatchToProps)(Index);

Sachin Metkari
la source