1

I have a simple app that access the opentable api (http://opentable.herokuapp.com/api/restaurants). My app, when loaded, simply displays content specified from the query parameters. For example, appending ?city=toronto would give me all restaurants in Toronto. Here is a working, hardcoded example:

import React, { Component } from "react";
import Spinner from "./components/common/Spinner";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      items: [],
      isLoading: false
    };
  }

  componentDidMount() {
    // // let city = this.props.match.params.city;
    // // console.log(city);
    // console.log(this.props.match.params.city);
    fetch("http://opentable.herokuapp.com/api/restaurants?city=Toronto")
      .then(res => res.json())
      .then(json => {
        this.setState({
          isLoading: true,
          items: json
        });
      });
  }
  render() {
    const { isLoading, items } = this.state;
    let itemsToArray = Object.values(items);
    return !isLoading ? (
      <div>
        <Spinner />
      </div>
    ) : (
      <div className="App">
        <ul>
          {itemsToArray[3].map(item => (
            <div>
              <li key={item.id}>{item.name}</li>
            </div>
          ))}
        </ul>
      </div>
    );
  }
}

export default App;

If I were to uncomment console.log(this.props.match.params.city);, it tosses an error TypeError: Cannot read property 'params' of undefined. Am I accessing the params incorrectly? I'd like to do something like,

componentDidMount() {
  let city = this.props.match.params.city;
  fetch(`http://opentable.herokuapp.com/api/restaurants?city=${city}`)
    .then(...
Mike K
  • 7,621
  • 14
  • 60
  • 120

3 Answers3

2

If you are trying to use something like:

http://myapp/page?city=Toronto

Then, this.props.match.params.city won't work. The reason being, the use-case of match.params.city is supposed to be in the Routes.

import { Route } from "react-router-dom";

<Route path="/path/:city" component={App} />

In your componentDidMount() lifecycle method, try using:

const urlParams = new URLSearchParams(window.location.search);
let city = urlParams.get('city');

For the above code, have a look at How can I get query string values in JavaScript? In your code, if you try logging the value of city, it might be undefined if you haven't configured your route this way.

Sample Code

class App extends React.Component {
  state = {
    city: "None"
  };
  componentDidMount() {
    const urlParams = new URLSearchParams(window.location.search);
    let city = urlParams.get("city");
    this.setState({
      city
    });
    console.log(city);
  }
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <h3>You are in {this.state.city}!</h3>
      </div>
    );
  }
}

Working Demo: CodeSandbox

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
0

You can use this function to access the URL params

var getParams = function (url) {   
    var params = {};
    var parser = document.createElement('a');
    parser.href = url;
    var query = parser.search.substring(1);
    var vars = query.split('&');
    if(vars == ''){
        params = '';
        return params;
    }
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        params[pair[0]] = decodeURIComponent(pair[1]);
    }
    return params;
};

and call it

console.log(getParams(window.location.href));
Wushu06
  • 93
  • 2
  • 10
0

What if you try to wrap your App Class component with withRouter? so, it will look like the following:

import React, { Component } from "react";
import { withRouter } from 'react-router-dom';
import Spinner from "./components/common/Spinner";

class App extends Component {
  //....
}

export default withRouter(App);
Bayu
  • 2,340
  • 1
  • 26
  • 31