'dispatch' no es una función cuando el argumento de mapToDispatchToProps () en Redux

124

Soy un principiante javascript / redux / react construyendo una pequeña aplicación con redux, react-redux, y react. Por alguna razón, cuando uso la función mapDispatchToProps junto con connect (react-redux vinculante) recibo un TypeError que indica que el despacho no es una función cuando intento ejecutar el accesorio resultante. Sin embargo, cuando llamo a dispatch como accesorio (vea la función setAddr en el código provisto) funciona.

Tengo curiosidad por saber por qué esto es así, en el ejemplo de la aplicación TODO en los documentos redux, el método mapDispatchToProps se configura de la misma manera. Cuando console.log (dispatch) dentro de la función dice que dispatch es type object. Podría seguir usando el despacho de esta manera, pero me sentiría mejor sabiendo por qué sucede esto antes de continuar con redux. Estoy usando webpack con babel-loaders para compilar.

Mi código:

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

Salud.

manchar
fuente
Estaba teniendo este problema y esto me ayudó a resolverlo
Alex W

Respuestas:

249

Si desea usar mapDispatchToPropssin un mapStateToPropssolo uso nullpara el primer argumento.

export default connect(null, mapDispatchToProps)(Start)

inostia
fuente
44
Esto es lo que he estado buscando. Ahora sé si solo quiero enviar algunas acciones.
Emperador Krauser
Esto es exactamente algo que estaba buscando. Gracias por la solución perfecta. ¿Qué sucede si no tenemos que usar mapDispatchToProps en ninguno de nuestros componentes? ¿Es de la misma manera que tenemos que manejar ese escenario?
Arun Ramachandran
1
Si no lo necesita mapDispatchToProps, simplemente no agregue ese argumento a connect:connect(mapStateToProps)(MyComponent)
inostia
107

Solo te falta el primer argumento connect, que es el mapStateToPropsmétodo. Extracto de la aplicación 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
fuente
3
¿Es obligatorio usar este método? Este método solo atrapa el estado ¿qué pasa si no necesitamos este método?
Muneem Habib
66
@MuneemHabib vea la respuesta de inostia sobre cómo no suministrar este método si no lo necesita
Brandon
21

Utilizar

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

en vez de

const StartContainer = connect(mapDispatchToProps)(Start)
Ana
fuente
5

Lo resolví intercambiando los argumentos, estaba usando

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

Cuál está mal. El mapStateToPropstiene que ser el primer argumento:

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

Parece obvio ahora, pero podría ayudar a alguien.

Amit Mittal
fuente
3

Necesitaba un ejemplo usando, React.Componentasí que lo estoy publicando:

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
fuente
3

Problema

Aquí hay un par de cosas a tener en cuenta para comprender el comportamiento del componente conectado en su código:

La aridad de los connectasuntos:connect(mapStateToProps, mapDispatchToProps)

React-Redux llama connectcon el primer argumento mapStateToPropsy el segundo argumento mapDispatchToProps.

Por lo tanto, aunque haya pasado en su mapDispatchToProps, React-Redux de hecho lo trata como si mapStatefuera el primer argumento. Aún obtiene la onSubmitfunción inyectada en su componente porque el retorno de mapStatese fusiona en los accesorios de su componente. Pero no es así como mapDispatchse supone que debe inyectarse.

Puede usar mapDispatchsin definir mapState. Pase en nulllugar de mapStatey su componente no estará sujeto a cambios en la tienda.

El componente conectado recibe dispatchpor defecto, cuando no mapDispatchse proporciona

Además, su componente recibe dispatchporque recibió nullpara su segunda posición para mapDispatch. Si pasa correctamente mapDispatch, su componente no recibirá dispatch.

Práctica común

Lo anterior responde por qué el componente se comportó de esa manera. Aunque, es una práctica común que simplemente pases a tu creador de acción usando mapStateToPropsla abreviatura del objeto. Y llame a eso dentro de su componente onSubmitEso es:

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
fuente
0

Cuando no proporcione mapDispatchToPropscomo segundo argumento, así:

export default connect(mapStateToProps)(Checkbox)

entonces recibirá automáticamente el envío a los accesorios del componente, por lo que puede simplemente:

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

sin ningún mapaDispatchToProps

Serge Nikolaev
fuente
0

Estoy usando así ... es fácil de entender el primer argumento es mapStateToProps y el segundo argumento es mapDispatchToProps al final se conecta con la función / clase.

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
fuente
si no tiene el primer argumento, simplemente pase nulo / indefinido y luego el segundo argumento ..
Abdul Moiz
0

En algún momento, este error también se produce cuando cambia el orden de la función Componente mientras pasa a conectarse.

Orden incorrecta:

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

Orden correcto:

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

Una pregunta que algunos podrían enfrentar está cubierta por esta pregunta, pero no se aborda en las respuestas, ya que es ligeramente diferente en la estructura del código pero devuelve exactamente el mismo error.

Este error ocurre al usar bindActionCreatorsy no pasar la dispatchfunción

Código de error

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)

Código fijo

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)

Faltaba la función dispatchen el código de error

soy Batman
fuente
0

La función React-redux 'connect' acepta dos argumentos primero es mapStateToProps y segundo es mapDispatchToProps verifique debajo de ej.

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

Si no queremos recuperar el estado de redux, establecemos nulo en lugar de mapStateToProps.

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

Sachin Metkari
fuente