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() { ... }
}