React: location.pathname, passing down url

Hey - I want a sort function that is determined by the url, the routes are set up in the parent App.js (and correspond to the heading of a column in a table).

At the moment location is coming up undefined.

  sortCities = () => {
    switch (this.props.location.pathname) {
      case "cities/city":
        return this.props.cities.sort((a, b) => {
          return a.city.localeCompare(b.city);
        });
      case "cities/country":
        return this.props.cities.sort((a, b) => {
          return a.country.localeCompare(b.country);
        });
      default:
        return this.props.cities;
    }
  };

the route in App.js looks like this:

<Router history={history}>
          <div>
            <Switch>
              <Route
                path="/cities"
                render={props => (
                  <CityIndex
                    {...props}
                    cities={this.state.cities}
                    // url={this.props.location.path}
                  />
                )}
              />

Do you have a working demo?

Can’t see anything wrong yet.

I’ve just managed to use debugger to show that the location is being passed down properly, but when I use it to pass into the sort method something breaks:

render() {
    const renderedCities = this.sortCities();
    return (
      <div>
        <table border="1" className="table">
          <thead>
            <tr>
              <th>
                <Link to={`/cities/id`}>ID </Link>
              </th>
              <th>
                <Link to={`/cities/city`}>City </Link>
              </th>
              <th>
                <Link to={`/cities/country`}>Country </Link>
              </th>
    
            </tr>
          </thead>
          <tbody>
            {renderedCities.map(city => {
              return (
                <tr key={city.city}>
                  <td>{city.client_city_id} </td>
                  <td>

^ the map says it is undefined

So you have said that you said that the value of this.props.location.pathname is confirmed to be correct. Can you also confirm the value of this.props.cities in your sortCities method? We would expect it to be an array of objects with city and country properties based on the code you’ve written.

Also just to save you from potential headaches in the future remember that in javascript Array.sort will mutate the original array, not return a new one, so every time you sort this.props.cities you are mutuating your props, which is a no-no in react world.

yeah thanks! I realised that and have changed it to spreading the array. The array is populated correctly yes, the unsorted table is rendered without trouble but clicking the column headers at the moment does nothing (I changed these from a href tags).

I’ve also realised the classic error of not triggering a re-render by setting state so now it looks like this but setState is in the wrong place:

class CityIndex extends React.Component {
  state = {
    cities: this.props.cities,
    sortedCities: []
  };

  sortCities() {
    let sortedCities = [...this.state.cities];
    switch (this.props.location.pathname) {
      case "cities/city":
        return sortedCities.sort((a, b) => {
          return a.city.localeCompare(b.city);
        });
      case "cities/country":
        return sortedCities.sort((a, b) => {
          return a.country.localeCompare(b.country);
        });
      default:
        return sortedCities;
    }}
    this.setState({
      sortedCities: sortedCities
    });