Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grab active route using react router v4 #4793

Closed
alansouzati opened this issue Mar 21, 2017 · 8 comments
Closed

Grab active route using react router v4 #4793

alansouzati opened this issue Mar 21, 2017 · 8 comments

Comments

@alansouzati
Copy link

First of all, thanks for working on React Router v4. I like the changes applied in the new version, really clean API, really well done.

I work on Grommet, an UX framework that runs on top of ReactJS and supports React Router.

Recently I tried to start our migration to support react router v4. In the past we used to be completely un-opinionated about routing. But recently we added support for React Router inside our Anchor component. We do not use Link or NavLink, we use a prop called path to identify when to use React router and when not to use it.

React router Anchor: <Anchor path="/test" icon={<PreviousIcon />} />
Anchor without React Router: <Anchor href="/test" icon={<PreviousIcon />} />

I'm calling history.push and history.replace in a very similar way that React Router <Link /> does.

The problem I'm facing with v4 is that this.context.router.isActive is completely gone. I tried to find a reason why, or some migration guide, without success. Here is our current implementation of the Anchor that uses React v3:

https://github.com/grommet/grommet/blob/master/src/js/components/Anchor.js#L23

Well, I tried looking into the new <NavLink /> implementation and it seems now things are very JSX-driven. From what I understood from this component it seems that you are declaring a new <Route /> to be able to get a match in the callback. Initially this seems odd to me as I'm not creating a new Route but trying to identify if a given path is active or not.

Could you please explain why router.isActive is gone and what would be a way to get the active route without using JSX for that?

@pshrmn
Copy link
Contributor

pshrmn commented Mar 21, 2017

Rendering a <Route> does not necessarily mean "only render when you match the current location". For example, it can be used inject the router variables from the context into a component as props.

In <NavLink>, the <Route> is using the children prop, which means that it will call the children function whether or not the route matches. If the match is null, then we know that it did not match.

If you would prefer not to use <Route children> in this way, React Router offers an imperative approach with the matchPath function. This is what <Switch>es and <Route>s use internally to match a location against a path.

@alansouzati
Copy link
Author

Thanks let me try that right now 👍 appreciate the explanation.

@alansouzati
Copy link
Author

I tried but it is always returning the root path.

screen shot 2017-03-20 at 9 13 49 pm

As you can see when the path is /dashboard I would expect the return to be that, and not /.

Here is how I'm describing the Routes:

<Router>
        <App centered={false}>
          <Split priority={priority} flex='right'
            onResponsive={this._onResponsive}>
            {nav}
            <div>
              <Route exact={true} path='/' component={Dashboard} />
              <Route path='/login' component={Login} />
              <Route path='/dashboard' component={Dashboard} />
              <Route exact={true} path='/tasks' component={Tasks} />
              <Route path='/tasks/:id' component={Task} />
            </div>
          </Split>
        </App>
      </Router>

@alansouzati
Copy link
Author

alansouzati commented Mar 21, 2017

By inspecting how matchPath works, it expects you to send the path as an option, otherwise it will use / by default.

In v3 isActive module receives the existing routes:

https://github.com/ReactTraining/react-router/blob/v3/modules/isActive.js#L125

and I don't think matchPath does that.

@pshrmn
Copy link
Contributor

pshrmn commented Mar 21, 2017

I'm not actually sure where you are logging.

Anyways, this is the matchPath implementation I was referring to. The important thing to remember is that partial matches will be "active", so if you only want the path to be "active" when it completely matches, you will need to pass the exact: true option to matchPath or check the returned match object's isExact property.

let active = false
const { router } = this.context
const { path } = this.props
if (path && router) {
  const { location } = router
  active = matchPath(location.pathname, { path }) != null
}
this.setState({ active })

@alansouzati
Copy link
Author

Thanks this works!

@a-eid
Copy link

a-eid commented May 4, 2017

using context is usually not a good idea I am having this problem right now and kinda found a work around . i'll paste some code here .

export default () => (
  <Router>
    <div>
      <Route path="/:active?" component={Nav} />
      <div className="container">
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
      </div>
    </div> 
  </Router>
)

here I am rendering nav on every every path basically and giving it a name active and making it optional for home

now I can check for match.params.active in nav component it gives the full path .
heres an example

        <div className="nav navbar-nav" >
          <li className={!match || !match.params || !match.params.active ? "active" : ""}><NavLink to="/">Home</NavLink></li>
          <li className={match.params.active === 'about' ? "active" : ""}><NavLink to="/about">About</NavLink></li>
          <li className={match.params.active === 'notfound' ? "active" : ""}><NavLink to="/notfound">nothing</NavLink></li>
        </div>

@asfktz
Copy link

asfktz commented Jun 2, 2017

Is this relevant to you?
https://reacttraining.com/react-router/web/api/NavLink

See also the implementation:
https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/NavLink.js

@lock lock bot locked as resolved and limited conversation to collaborators Jan 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants