2

I am using redux-thunk recently, and meet such case:

In signup action creator function, i wanna do history.push after i dispatch a signup success action, the code may look like this:

// SignupAction.js

export const signupRequest = (userData) => {
  return dispatch => {
    dispatch(signupPending())

    return axios.post('/api/user', userData)
      .then(res => dispatch(signupSuccess()))
      .then(() => {
        // wanna do history.push('/') to the home page after successfully signup
      })
      .catch(error => dispatch(signupFailure(error.message)))
  }
}

Right now i am confused, I am trying to put all the logic into one action, but there is no way to inject the history into my signup action. I can give the signupRequest the function a second argument, it could be the history object itself: signupRequest(userData, history), or i can just pass a callback: signupRequest(userData, callback). However i am not sure which one is better.

There's also an alternative way to get history, i don't need put all logic in a single action, so the signup action would just simply return a promise, and i will deal with it later in the component, in this case, accessing the history would be quite straightforward:

// signupAction.js

export const signupRequest = (userData) => {
  return dispatch => {
    return axios.post('/api/users', userData);
  }
}

// signupForm.js
export default class SignupForm extends Component {
  // ...
  handleSubmit = e => {
    const userData = e.target.value
    this.props.signupRequest(userData)
      .then(() => this.props.dispatch(signupSuccess()))
      .then(() => {
        // now i can easily access history inside the component
        this.props.history.push('/')
      })
      .catch(error => dispatch(signupFailure(error.message)))  }
}

So which way should i follow, and is there any best practice to solve this problem?

Limboer
  • 373
  • 4
  • 24

1 Answers1

2

Not sure if this is the best practice, but i see some people do it like this: solution

The key is to put history in a single file so that we can reference it and use it outside the component:

First create a history object in a standalone file:

// history.js
import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Then wrap it in the Router component, be sure to use Router rather than BrowserRouter:

import { Router, Route } from 'react-router-dom';
import history from './history';

ReactDOM.render(
  <Router history={history}>
    ...
  </Router>
)

Finally in redux actionCreators we are able to import the history object and use it:

// SignupAction.js
import history from './history'

export const signupRequest = (userData) => {
  return dispatch => {
    dispatch(signupPending())

    return axios.post('/api/user', userData)
      .then(res => dispatch(signupSuccess()))
      .then(() => {
        // we are reference/use the same `history` all the time by import it
        history.push('/')
      })
      .catch(error => dispatch(signupFailure(error.message)))
  }
}

So basically i still prefer to put logic inside the actionCreator, the component should only focus on UI rendering, the logic should be dealt by redux instead.

Limboer
  • 373
  • 4
  • 24
  • 1
    This doesn't render the page after redirecting, might not be working anymore. – Imnotapotato Oct 01 '21 at 20:20
  • @W.Doch What do you mean by not rendering the page, or you might got a better solution? – Limboer Oct 02 '21 at 17:41
  • 1
    no other solution.. I think they changed something with the packages. It does redirect but do not render the page/compontnet content. and it seems like a common issue (i saw that same way so solve the problem on other posts and comments about it not working anymore) – Imnotapotato Oct 03 '21 at 17:28
  • @W.Doch React Router v6 has just been released, I have seen a few questions asked about how to navigate(or `history.push`) out of React context: https://stackoverflow.com/q/61858941/12733140 and https://stackoverflow.com/q/64192320/12733140. However currently no solutions provided, if you find answer, just comment it below, thanks! – Limboer Nov 07 '21 at 15:06