Home > Back-end >  react is not updating components using state in class
react is not updating components using state in class

Time:10-05

so first of all I am trying to assign null values to the state component and then assign them values later so here is my constructor of a class

constructor(props){
        super(props);
        this.state = {
            Countrys:null,
            States:null,
            Citys:null
        }
    }

and then I am asigning them value is ComponentDidUpdate function so here is my componentDidMount function

componentDidMount() {
        navigator.geolocation.getCurrentPosition(function(position) {
          console.log(position)
          console.log("Latitude is :", position.coords.latitude);
          console.log("Longitude is :", position.coords.longitude);
        });
        this.setState({
          Countrys:Country.getAllCountries(),
            States:State.getAllStates(),
            Citys:City.getAllCities()
        })
        
        /*console.log("Country:: " Country.getAllCountries()[0].name);
        console.log("City:: " City.getAllCities()[0].name);*/

      }

and then I am trying to access them in my jsx elements in return using map like this

 {this.state.Citys.map((ele ,index) =>
          <option value={`${ele}`} className="d-inline mx-2 col-sm-5" onClick={({target}) => target.classList.toggle('bg-primary')}>
          {ele.name}
         </option>
      )}

but its showing me error that

TypeError: Cannot read properties of null (reading 'map')

can anyone tell me what is wrong here or how to correct it and when I am trying to assign City.getAllCities() like functions directly to this.state instead of assigning them with null it shows me page unresponsive

And City.getAllCities(), Country.getAllCountries(), State.getAllStates() are from npm package "country-state-city"

CodePudding user response:

The first render will have state.Citys set to null, as you've set in the constructor.

ComponentDidMount will only fire after the first render.

you should initialized the state in the constructor

CodePudding user response:

As Bernardo Ferreira Bastos Braga mentioned, state.Citys is null in the first render.
One thing you can do to avoid the error is to render conditionally.

 {this.state.Citys !== null && this.state.Citys.map((ele ,index) =>
          <option value={`${ele}`} className="d-inline mx-2 col-sm-5" onClick={({target}) => target.classList.toggle('bg-primary')}>
          {ele.name}
         </option>
      )}

Or

 {this.state.Citys === null ? <SomeOtherComponent/Element/EmptyFragment/etc.. /> : this.state.Citys.map((ele ,index) =>
          <option value={`${ele}`} className="d-inline mx-2 col-sm-5" onClick={({target}) => target.classList.toggle('bg-primary')}>
          {ele.name}
         </option>
      )}

In these examples, the map function won't be called if state.Citys is null.

CodePudding user response:

If, like you mentioned, you're using country-state-city, then there is no reason to defer loading those three values until componentDidMount at all: they're static imports from the country-state-city package.

Just import them at the top of your file, create your initial state in your constructor, assign those values, and you're done without any null states during render.

import { Component } from "react";
import { Country, State, City }  from "country-state-city";
...

export class YourClass extends Component {
  constructor(props) {
    super(props);
    this.state = {
      countries: Country.getAllCountries(),
      states: State.getAllStates(),
      cities: City.getAllCities()
    };
  }

  render() { ... }
}
  • Related