0

I was trying to trigger an event after redux state have been updated so I ran a promise .then like this

logoutHandler = (event) => {
    console.log("logout Handler")
    event.preventDefault()
    window.FB.logout()
    this.props.LoggedIn(false).then(() => {
        this.props.history.replace('/signup');
    })
}

Notice this..

  this.props.LoggedIn(false).then(() => {
            this.props.history.replace('/signup');
        })

Where .LoggedIn(false) is a redux action.

This is throwing an error

Cannot read property 'then' of undefined

This is my redux action

export const LoggedIn  = (isLoggedIn) => {
  return function (dispatch) {
    dispatch({
      type: USER_LOGGED_IN ,
      payload: isLoggedIn
    })
  }
}

Question: Can someone tell me what I would be doing wrong here?

Constantin Chirila
  • 1,979
  • 2
  • 19
  • 33
Alwaysblue
  • 9,948
  • 38
  • 121
  • 210

4 Answers4

1

You need to return a Promise.

So instead do something like this:

logoutHandler = (event) => {
  event.preventDefault()
  window.FB.logout()
  return this.props.LoggedIn(false).then(() => {
    this.props.history.replace('/signup');
    return Promise.resolve(); // Just return a resolved promise
  })
}
lumio
  • 7,428
  • 4
  • 40
  • 56
  • Do I need to include the promise as done by Shubham Khatri in my redux action as well? Also, Can you please explain that how we can resolve a promise we made in redux action here `this.props.LoggedIn(false).then(() => { this.props.history.replace('/signup'); return Promise.resolve(); // Just return a resolved promise })` – Alwaysblue Oct 22 '18 at 08:04
1

As per redux-thunk doc, you should return Promise from your inner function to use .then with the action.

Any return value from the inner function will be available as the return value of dispatch itself. This is convenient for orchestrating an asynchronous control flow with thunk action creators dispatching each other and returning Promises to wait for each other’s completion:

Take a look at the document here.

The possible code has already shared by Shubham Khatri

Prasun
  • 4,943
  • 2
  • 21
  • 23
0

Your Redux action isn't returning a Promise. Either you can create and return a new Promise

export const LoggedIn  = (isLoggedIn) => {
  return function (dispatch) {
    return new Promise((resolve, reject) => {
         dispatch({
             type: USER_LOGGED_IN ,
             payload: isLoggedIn
         })
         resolve();
    })
  }
}

or execute, history.replace from within the redux action itself

export const LoggedIn  = (isLoggedIn, history) => {
  return function (dispatch) {
    dispatch({
      type: USER_LOGGED_IN ,
      payload: isLoggedIn
    });
    history.replace('/signup');
  }
}


logoutHandler = (event) => {
    console.log("logout Handler")
    event.preventDefault()
    window.FB.logout()
    this.props.LoggedIn(false, this.props.history);
}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • When I follow your first code snippet and do something like this `export const LoggedIn = (isLoggedIn) => { return function (dispatch) { return new Promise((reject, resolve) => { dispatch({ type: USER_LOGGED_IN , payload: isLoggedIn }) resolve(); }) } }` it throws **Uncaught (in promise)** Also, Shubham can you please-please explain your answer about why I need to use promise in action – Alwaysblue Oct 22 '18 at 08:02
  • You are using a .then in your code and hence you need to return a Promise – Shubham Khatri Oct 22 '18 at 08:04
  • @KuchBhi, I made a small mistake in my arguments order, please check the updated code – Shubham Khatri Oct 22 '18 at 08:06
  • Doesn't `dispatch` already return a promise? If so, avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! At least, use `Promise.resolve()` instead of `new Promise`. – Bergi Oct 22 '18 at 10:43
0

To implement anything related to state update, you can use react life cycle method componentDidUpdate(). whenever redux reducer returns a new state whole react applications gets re-rendered. After rendering, componentDidUpdate method is executed for every component.

componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.

componentDidUpdate() {
  if (condition) {
     this.props.history.replace('/signup');
  }
}

https://reactjs.org/docs/react-component.html#componentdidupdate

Raj Kumar N
  • 783
  • 6
  • 22