Redux Router - "Dispatch is not defined"

42,258

You need your action to return a function to utilize the thunk middleware, then redux will inject the dispatcher into it. You mixed your dispatcher invocation with the implementation detail. The following snippet fixes both defects.

guestLoginRequest: function(){
  return function (dispatch) {
    var ref = new Firebase("https://penguinradio.firebaseio.com");
    ref.authAnonymously(function(error, authData) {
      if (error) {
        console.log("Login Failed!", error);
      } else {
        console.log("Authenticated successfully with payload:", authData);
        dispatch(actions.setLoginStatus(true, authData))
        console.log("dispatched");
      }
    });
  }
}

In addition, you need to dispatch your action correctly on the Login class.

dispatch(this.props.actions.guestLoginRequest())

Your action invocation is always done by invoking dispatch. The flow should be something like this:

React component --> dispatch ---> API call (thunk middleware) --> dispatch ---> reducer
Share:
42,258
Mike
Author by

Mike

Updated on July 09, 2022

Comments

  • Mike
    Mike almost 2 years

    I've got a simple component that calls an action when a user loads a page, and inside that action, I'm trying to dispatch another action to set the loggedIn state of the store to true or false:

    import React, { Component } from 'react'
    import { Link, browserHistory } from 'react-router'
    import $ from 'jquery'
    
    class Login extends Component {
    
      constructor(props) {
        super(props)
      }
      componentDidMount() {
        this.props.actions.guestLoginRequest()
      }
      render() {
        return (
          <div>
            <div classNameName="container">
              <div className="row">
                We are signing you in as a guest
              </div>
            </div>
          </div>
        )
      }
    }
    
    export default Login
    

    I can get the login information when the guestLoginRequest action is called, but when I try to dispatch another action inside of it, nothing happens:

    guestLoginRequest: function(){
        var ref = new Firebase("https://penguinradio.firebaseio.com");
        ref.authAnonymously(function(error, authData) {
          if (error) {
            console.log("Login Failed!", error);
          } else {
            console.log("Authenticated successfully with payload:", authData);
            return dispatch => {
              dispatch(actions.setLoginStatus(true, authData))
              console.log("dispatched");
            };
          }
        });
      }
    

    I get an error of Uncaught ReferenceError: dispatch is not defined when I remove the return dispatch => { } statement. In my store I am using redux-thunk, so I can dispatch inside of actions:

    // Store.js
    import { applyMiddleware, compose, createStore } from 'redux'
    import rootReducer from './reducers'
    import logger from 'redux-logger'
    import thunk from 'redux-thunk'
    
    let finalCreateStore = compose(
      applyMiddleware(thunk, logger())
    )(createStore)
    
    
    export default function configureStore(initialState = { loggedIn: false }) {
      return finalCreateStore(rootReducer, initialState)
    }
    

    I am mapping the dispatch to props in my app.js as well:

    function mapStateToProps(state) {
      return state
    }
    function mapDispatchToProps(dispatch) {
      return {
          actions: bindActionCreators(actions, dispatch)
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(App)
    

    Just in case it could be helpful, here is my client.js and reducer files:

    // client.js
    import React from 'react'
    import { render } from 'react-dom'
    import App from '../components/App'
    import configureStore from '../redux/store'
    import { Provider } from 'react-redux'
    
    
    let initialState = {
      loggedIn: false
    }
    
    let store = configureStore(initialState)
    
    render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('app')
    )
    // Reducer.js
    import { combineReducers } from 'redux'
    
    let LoginStatusReducer = function reducer(loggedIn = false, action) {
      switch (action.type) {
        case 'UPDATE_LOGIN_STATUS':
          return loggedIn = action.boolean
        default:
          return loggedIn
      }
    }
    export default LoginStatusReducer
    
    const rootReducer = combineReducers({
      loggedIn: LoginStatusReducer
    })
    
    export default rootReducer
    

    Any ideas why my dispatch function isn't working? I'm confused since I did set up redux-thunk with my store, and I'm using code similar to the docs when I call return dispatch => { }. Is there something I'm missing? Thank you in advance for any advice!

  • Mike
    Mike about 8 years
    I've replaced my action with the one you posted above, and updated the dispatch call on Login.js, but I am getting a " dispatch is not defined" on the Login.js file. Do I have to pass in that function to the Login component? Also should I be calling return function (dispatch) instead of return function (dispatcher)?
  • Matt Lo
    Matt Lo about 8 years
    You'll need to expose a wrapper around the store's dispatch (via mapDispatchToProps) or get the store's dispatcher directly (store.dispatch). Here's an implementation example: Component - github.com/mattlo/consultant-app/blob/master/src/client/… Store export - github.com/mattlo/consultant-app/blob/master/src/client/data‌​/…
  • Mike
    Mike about 8 years
    I've updated my answer to include my mapDispatchToProps function, does it look right?