4

I have following route. When I'm at /createtest page and doing history.push(/createtest/some-test-id) as it matches the same route component, it is not reloaded. Is there any smart solution? Or I need to check match params and implement logic to reload?

(react 16, router v4)

<Route path="/createtest/:testid?/:type?/:step?/:tab?" render={(props) => <CreateTest user={user} {...props}/>}/>
sapy
  • 6,665
  • 6
  • 40
  • 51
  • Does [this answer](https://stackoverflow.com/questions/51751075/api-call-after-reloading-same-route-via-react-router/51751268#51751268) answer your question? – Tholle Aug 08 '18 at 18:19
  • So reading match params and manually reloading is a solution I knew as I mentioned in the question. Looking for smart solutions. – sapy Aug 08 '18 at 18:21
  • You need to use `exact` props. refer to this link https://stackoverflow.com/questions/49162311/react-difference-between-route-exact-path-and-route-path – nine9stars Aug 08 '18 at 18:22

3 Answers3

8

You could give the URL parameters as key to the component so that an entirely new component will be created when a URL parameter changes.

<Route
  path="/createtest/:testid?/:type?/:step?/:tab?"
  render={props => {
    const {
      match: {
        params: { testid, type, step, tab }
      }
    } = props;
    return (
      <CreateTest
        key={`testid=${testid}&type=${type}&step=${step}&tab=${tab}`}
        user={user}
        {...props}
      />
    );
  }}
/>;
Tholle
  • 83,208
  • 13
  • 152
  • 148
  • 1
    This is a very very smart solution. I'll accept it once I implement it and I see it works (cause react 16 might not refresh on basis of `key` ). But pretty smart though – sapy Aug 08 '18 at 18:35
  • 1
    Absolute genius. So simple, yet so elegant. It worked – sapy Aug 09 '18 at 19:30
  • Could someone explain the syntax here? Its an anonym function fed to the render property of the route, that returns the jsx, and we somehow take just the needed url params and make a key prop for the component, right? But how does that const {} = props thing work? – rayaqin Oct 07 '20 at 13:44
  • @rayaqin It's called [object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring). It's essentially just sugar for `const testid = props.match.params.testid, type = props.match.params.type, ...` – Tholle Oct 08 '20 at 13:03
0

You can try this

const Reloadable = (props) => {
    const { location } = props
    const [key, setKey] = useState(location.key)

    if (location.key !== key) {
        setTimeout(() => setKey(location.key), 0)
        return null
    }
    return <>{props.children}</>
}

<Route path="/" exact render={({ history, location }) => (
    <Reloadable location={location}>
        <SomeComponent />
    </Reloadable>)}
/>
-1

See this doc. https://reacttraining.com/react-router/web/api/Route/exact-bool

The exact param comes into play when you have multiple paths that have similar names:

For example, imagine we had a Users component that displayed a list of users. We also have a CreateUser component that is used to create users. The url for CreateUsers should be nested under Users. So our setup could look something like this:

Now the problem here, when we go to http://app.com/users the router will go through all of our defined routes and return the FIRST match it finds. So in this case, it would find the Users route first and then return it. All good.

But, if we went to http://app.com/users/create, it would again go through all of our defined routes and return the FIRST match it finds. React router does partial matching, so /users partially matches /users/create, so it would incorrectly return the Users route again!

The exact param disables the partial matching for a route and makes sure that it only returns the route if the path is an EXACT match to the current url.

So in this case, we should add exact to our Users route so that it will only match on /users:

nine9stars
  • 239
  • 2
  • 11
  • Doesn't work . May be I failed to explain the problem, but this doesn't fix the issue . – sapy Aug 09 '18 at 19:29