React: this/props/state

Hi all,

I’m getting a bit tangled up with this/props and state, specifically when using a switch case. This file receives ‘cities’ from App.js. I wanted to pass in this.props.cities to the switch case but this errored the fat arrow, not sure why.

The error I’m currently getting is TypeError: Cannot read property ‘map’ of undefined, but I had been getting can’t map over renderedCities. If someone could get me back on track that would be great!

class CityIndex extends React.Component {
  state = {
    cities: this.props.cities
  };

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

  render() {
    const renderedCities = this.sortCities(this.props.location.pathname);
    return (
.....
{renderedCities.map(city => {
              return ....

(the bits I’ve omitted are just table bits)

There are few issues you’re running into here.

First, you’ve written sortCities as a function which accepts the entire props object as an argument and then attemps to perform some logic and return an array.

In your render method, you call sortCities but pass into it as an argument this.props.location.pathname instead of the full props object as your function is defined to receive.

Then your function references the props object stored on the class by calling setting up a switch statement with this.props.location.pathname. You should make a decision if you’re going to just reference the props object on the class in the method or pass it in as an argument, right now you’re doing both and it is confusing you.

Your sortCities function is not working as you intend it to and returning undefined instead of an array. renderedCities is then set to undefined in the render method. Then later on in the method you attempt to map over the renderedCities array but it is infact undefined so you get a TypeError

It may be helpful to put some breakpoints in your code so you can see how it is executing and what your logic is returning, etc. If you’re unsure of how to do this you can reference this article here

This sounds very helpful, I’ll work through the points you make - thank you!

1 Like

here is the new version, I got rid of state altogether. I think the problem may lie in the router / passing down the location? I’m currently reading about withRouter to try and solve it:

class CityIndex extends React.Component {
  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;
    }
  };

  render() {
    const renderedCities = this.sortCities();
...
   {renderedCities.map(city => {
              return (
...

the route is provided as props I think automatically with router. This is from App.js:

 render() {
    return (
      <div className="ui-container">
        <Header />

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