Mike K
Mike K

Reputation: 6511

Unable to read params property from query string?

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(...

Upvotes: -1

Views: 97

Answers (3)

Bayu
Bayu

Reputation: 2654

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);

Upvotes: 0

Praveen Kumar Purushothaman
Praveen Kumar Purushothaman

Reputation: 167212

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

Upvotes: 2

Wushu06
Wushu06

Reputation: 93

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));

Upvotes: 0

Related Questions