20

Let's say I have a Link that sends me to a page for adding/editing a list entry.

How do I dispatch a Redux action when I click on the Link itself so that I can update the Redux store first, before actually getting redirected to that page.

Eg: I click on Edit button -> Action is dispatched -> Store updated, {'state': 'edit-mode'} -> Proceed to redirect.

Or do you have another way in mind to accomplish what I'm trying to do?

Maybe when component has mounted, then I will run an action like stateToEdit based on certain conditions? If so, then please show to me your way. Thanks

PS: I'm using only one component for all add/edit/delete. So I'm thinking of a way to render based on the state whether its on edit-mode or delete-mode etc.

Joshua Rajandiran
  • 2,788
  • 7
  • 26
  • 53
  • 6
    Instead of using `Link`, you could use `browserHistory.push(path)` with on `onClick` function. Inside this function, dispatch your action, then push to the new location. – lux Jul 14 '16 at 16:06
  • I was also thinking of something like that but I'm not too sure if this is the right way to solve the problem. I guess I'll use this method for now. If there are other ways, then I'd like to know. Thanks – Joshua Rajandiran Jul 14 '16 at 16:27
  • 1
    A more appropriate way to address this issue might be to introduce `redux-thunk` which would probably help organize the code a bit more considering you probably want to perform this "dispatch something, then move to another page" action in various places. Take a peek at Dan's answer here, I'm sure it'll get the gears turning for how you could approach the issue in your context: http://stackoverflow.com/questions/35493352/can-i-dispatch-multiple-actions-without-redux-thunk-middleware/35642783#35642783 – lux Jul 14 '16 at 16:31
  • ^ As in, envision replacing one of those `dispatch(increment)` calls with a call to `browserHistory` – lux Jul 14 '16 at 16:32
  • Thanks for the reply & info. Can you put your replies as an answer so I can accept it? – Joshua Rajandiran Jul 14 '16 at 16:48

1 Answers1

17

Here are a couple ways you could go about addressing this issue:

  1. Instead of using Link, try utilizing browserHistory.push(path) with an onClick function.
    • Inside the onClick, you can dispatch your action, then push to a new location.
    • However, if you want to perform this series of actions in various components, you will probably suffer from code duplication.
  2. A more robust way to address this issue would be to implement redux-thunk, which provides a generic way of performing multiple "actions" (be it calling a Redux action, or performing an async operation, or both!) in response to a change.
    • Dan has a great response here highlighting the simplicity of what redux-thunk actually offers: Can I dispatch multiple actions without Redux Thunk middleware?
    • In your case, in the incrementTwice function, imagine just replacing one of the dispatch(increment) calls with a call to browserHistory.push(action.path), similar to the below:

Redux thunk action

export const dispatchThenRoute = (myAction, myPath) => {
    return (dispatch) => {
        dispatch(myAction)
        browserHistory.push(myPath);
    }
}; 
Community
  • 1
  • 1
lux
  • 8,315
  • 7
  • 36
  • 49
  • Link Prefetch won't work if we go with this approach. Am I correct? Or how to make it work! – master_dodo May 03 '17 at 14:55
  • 1
    In `react-router` v4 there is no `browserHistory`: how to deal with the dispatching and then the pushing if there is nothing to push to? – Aerendir Apr 24 '18 at 16:30
  • 1
    @Aerendir You can connect a component to the Router by using the `withRouter(App)` HOC. After this, `App` now access access to `location` and `history` in `props`. Just push to history as you normally would. Example `export default withRouter(App);` via https://github.com/mikechabot/react-boilerplate/blob/master/src/components/App.jsx – lux Apr 24 '18 at 16:54
  • 1
    What's wrong with `...`? – Sumit Jul 18 '18 at 13:56
  • @Sumit You could do that, but you'll double route if you pass your own `onClick` that pushes to a location (See https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/Link.js). – lux Jul 18 '18 at 14:50
  • @Sumit Also, if you're `onClick` performs an async action, there's no guarantee if it will complete by the time the new location is pushed in ``. With a thunk, you can control the flow. – lux Jul 18 '18 at 15:15