Arian
Arian

Reputation: 7719

React Router path wrongly matches

I'm using React v4.2 for my app, and it seems not to be matching the correct path for the routes:

  <Provider store={store}>
      <BrowserRouter>
        <div>
          <Switch>
            <Route path="/login" render={(props) => {
                if (isAuthenticated()) {
                  return <Redirect to='/' />;
                } else {
                  return <LoginForm {...props}/>
                }
              }
            } />
            <EnsureLoggedInContainer>
              <Route exact path="/group" render={(props) => {
                debugger;
                return <GroupList {...props}/>
              }
              }/>
              <Route exact path="/group/new" render={(props) => {
                debugger;
                return <GroupList {...props} modal={rr}/>;
              }
              } />
            </EnsureLoggedInContainer>
          </Switch>
        </div>
      </BrowserRouter>
  </Provider>

I have some links in the app, on which I click and I redirect the client to new URL:

  _onSubmit(values) {
    const { history } = this.props;
    this.props.createGroup(values, ({status}) => history.push('/group'));
  }

I inspect the values of props.history.location.pathname and props.match.path and they don't match. Why is this happening? Why is the correct route not matched?

Update 1

The code for EnsureLoggedInContainer:

class EnsureLoggedInContainer extends Component {
  componentDidMount() {
    if (!isAuthenticated()) {
      dispatch(setRedirectUrl(currentURL))
      this.props.history.replace("/login")
    }
  }

  render() {
    if (isAuthenticated()) {
      return(
        <div>
          <AppNavBar />
          <ComponentsNavBar />
          {this.props.children}
        </div>
      );
    } else {
      return <noscript />;
    }
  }
}

export default EnsureLoggedInContainer;

Update 2

I changed the router configuration code to the following:

ReactDOM.render(
  <Provider store={store}>
      <BrowserRouter>
        <div>
          <Switch>
            <Route exact path="/login" render={(props) => {
                if (isAuthenticated()) {
                  return <Redirect to='/' />;
                } else {
                  return <LoginForm {...props}/>
                }
              }
            } />
            <Route exact path="/register" render={(props) => {
                if (isAuthenticated()) {
                  return <Redirect to='/' />;
                } else {
                  return <RegisterForm {...props}/>
                }
              }
            } />
            <EnsureLoggedInContainer>
              <Route exact path="/group" component={GroupList} modal={newGroupModal}/>
              <Route exact path="/group/new" component={GroupList}/>
              <Route component={Home} />
            </EnsureLoggedInContainer>
          </Switch>
        </div>
      </BrowserRouter>
  </Provider>
  , document.querySelector('.container'));

And changed the last line of EnsureLoggedInContainer to :

export default withRouter(EnsureLoggedInContainer);

But still, I get Home always being rendered, and random URLs being matched to unrelated routes (e.g. /group/new)

Upvotes: 2

Views: 5125

Answers (2)

Arian
Arian

Reputation: 7719

I finally managed to resolve the issue by using the private route pattern.

Upvotes: 1

Shubham Khatri
Shubham Khatri

Reputation: 281626

As per the documentation:

A match object contains information about how a matched the URL. match objects contain the following properties:

params - (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path

isExact - (boolean) true if the entire URL was matched (no trailing characters)

path - (string) The path pattern used to match. Useful for building nested <Route>s

url - (string) The matched portion of the URL. Useful for building nested <Link>s

while

Locations represent where the app is now, where you want it to go, or even where it was.

so if you are on say /group/new, location.pathname will give you /group/new whereas match.path will give your the Route path defined for the component in which you log it if it is matched

Upvotes: 2

Related Questions