Ricky
Ricky

Reputation: 2750

React Query String showing 404 when provided with query parameter

I am new to React and trying to render a page based on the name query like http://localhost:3000/show?name=james

So I initially added the Route as :

<BrowserRouter>
<Switch>    
<Route path='*' component={ErrorComponent} />} />
<Route path="show(/:name)" name="name" component={Show}></Route>
</Switch>
</BrowserRouter>

And then I tried to render the component Show like below:

import React, { Component } from 'react';
import queryString from 'query-string';
class Show extends Component {
  componentDidMount(){
    console.log(this.props.location.search);
    const values = queryString.parse(this.props.location.search);
    console.log(values.name);
  }


  render() {
    const { params } = this.props.match;
    return <div>
      <h4>About</h4>
      <p>This is About page.</p>
      {params.id ? <b>ID: {params.id}</b> : <i>ID is optional.</i>}
    </div>
  }
}

export default Show;

then when I try to show the page

http://localhost:3000/show?name=james

It always show 404. Not sure which part I am doing it wrong. Any help is appreciated. Also I am using react-router-dom 5.1.2 . Thanks.

Upvotes: 0

Views: 2840

Answers (2)

Zachary Haber
Zachary Haber

Reputation: 11027

EDIT: Can't believe I didn't notice this originally...

You need to put your path="*" route at the bottom of the Switch otherwise it'll match everything and anything below it won't even have a chance to match since Switches match only a single route. The description of making sure you have your route path set up correctly (below) is applicable as well, of course.

      <Switch>
        <Route path="/show/:name?" component={ShowRouteParam} />
        <Route path="*">ERROR 404</Route>
      </Switch>

https://codesandbox.io/s/elated-browser-d0sew?file=/src/App.js


The routes don't match query parameters.

"Please note: The RegExp returned by path-to-regexp is intended for use with pathnames or hostnames. It can not handle the query strings or fragments of a URL."

Depending on how you want to do it, you can either make the id an optional part of the route, or let it be a normal query parameters

Option 1:

<Route path="/show/:name?" component={Show}></Route>

component:

import React, { Component } from 'react';
import queryString from 'query-string';
class Show extends Component {
  componentDidMount(){
    console.log(this.props.location.search);
    const values = queryString.parse(this.props.location.search);
    console.log(values.name);
  }


  render() {
    const { params } = this.props.match;
    return <div>
      <h4>About</h4>
      <p>This is About page.</p>
      {params.name ? <b>ID: {params.name}</b> : <i>Name is optional.</i>}
    </div>
  }
}

export default Show;

Option 2:

<Route path="/show" component={Show}></Route>

component:

import React, { Component } from 'react';
import queryString from 'query-string';
class Show extends Component {
  componentDidMount(){
    console.log(this.props.location.search);
    const values = queryString.parse(this.props.location.search);
    console.log(values.name);
  }


  render() {
    const values = queryString.parse(this.props.location.search);
    return <div>
      <h4>About</h4>
      <p>This is About page.</p>
      {values.name ? <b>ID: {values.name}</b> : <i>Name is optional.</i>}
    </div>
  }
}

export default Show;

Working example: https://codesandbox.io/s/silent-rain-n61zs

Upvotes: 2

Drew Reese
Drew Reese

Reputation: 202658

path="show(/:name)"

This isn't a valid URL path to match on.

Redefine the path to ["/show/:id", "/show"]

<Route path={["/show/:id", "/show"]} name="name" component={Show} />

And since the Route is directly rendering the component, it can pull the query parameters and match parameters straight from props (this.props.match.params & this.props.location.search). Specifying two matching paths is equivalent to defining two separate Routes that render the same component. The same rules apply to path specificity, so define more complex matches first within the array.

class Show extends Component {
  componentDidMount(){
    console.log(this.props.location.search);
    const values = queryString.parse(this.props.location.search);
    console.log(values.name);
  }

  render() {
    const { params } = this.props.match;
    return <div>
      <h4>About</h4>
      <p>This is About page.</p>
      {params.id ? <b>ID: {params.id}</b> : <i>ID is optional.</i>}
    </div>
  }
}

Edit frosty-banach-9ou2q

Upvotes: 1

Related Questions