Crocsx
Crocsx

Reputation: 7609

How to handle URL parameter in react

I have an app in reactJs, using redux and router. I am sorry if this question is more about logic than code, but the problem is very narrow.

I have in my app different categories and each category will set the route like this :

/:category1/
/:category1/:item1
/:category1/:item1/:scheduling1

There is over 50 different route and I set them up all in my router.

        <PrivateRoute path="/:category1/:item1/:scheduling1" component={SchedulingComponent} />
        <PrivateRoute path="/:category1/:item1" component={ItemComponent} />
        <PrivateRoute path="/:category1" component={CateogryComponent} />

Now this work great when the user navigate in the app.

The problem I face is when the user reload the browser or access a link directly.

Since all those path are actually ids, If I access for example /:category1/:item1/:scheduling1

I need to dispatch 3 concatenated action in my redux store

selectCategory
selectItem
selectScheduling

The problem is I do not know how to correctly handle it.

I am confused if the best would be in each component's ComponentDidMount to dispatch some call (but it would also happen when the user navigate and those call are not needed)

Or if there is a way on first load to dispatch all the necessary action. Like making a component in <app> that would just read and dispatch the action when it's mounted (so only once)

Upvotes: 1

Views: 149

Answers (1)

HMR
HMR

Reputation: 39270

Not sure if this will work for you but maybe you can set redux state before rendering any route content:

function Connected({ Component, ...props }) {
  const dispatch = useDispatch();
  //route changed, dispatch action that will set redux state
  //  assuming this is a sync op
  dispatch({ type: 'PARAM_CHANGE', payload: useParams() });
  //render actual route content, redux state should have been set
  //  with the route parameters
  return <Component {...props} />;
}
const ConnectedRoute = ({
  component: Component,
  ...props
}) => (
  <Route
    {...props}
    render={props => {
      return <Connected Component={Component} {...props} />;
    }}
  />
);

In your route you can use ConnectedRoute:

<Switch>
  <ConnectedRoute
    path="/:id"
    component={SomeContentNeedingIdInReduxState}
  />
  <Route path="/" component={Home} />
</Switch>

The problem with this is that redux store follows react-router and when react-router changes route the route data will be copied in the store. When you play back actions in redux dev tools then it won't do what you expect.

To have react-router follow redux store and change route through actions you can use this package.

Upvotes: 1

Related Questions