New to React and building a geography app. I have an array of continents
uniqueRegions = ['Asia', 'America', 'Europe', 'Africa', 'Oceania', 'Polar']
in my props as this.props.uniqueRegions
. In my component, I want to set the state of a property visible
on each of those continents. I could hard-code it, but I don't want to do that. How can I possibly make that happen?
I tried using the spread operator as such
state = {
[ ...this.props.uniqueRegions]: {visible: 5}
};
but that obviously is incorrect syntax.
Also, I've tried initializing the visible property in setState, but it always returns undefined.
loadMore = (region) => {
console.log(this.state[region])
if(this.state[region])
this.setState(prevState => ({
[region]: {visible: 5}
}))
}
Below is how my region data is passed and currently set to State.
filterRegion = (region) =>{
if(region !==undefined ){
this.setState({
[region]: {countries: ['']}
})
return Axios
.get('https://restcountries.eu/rest/v2/region/' + region)
.then(res => {
if(res.status === 200 && res !== null){
this.setState(prevState =>({
[region]: {...prevState[region],
countries: (res && res.data || [])}
}))
} else {
throw new Error('No country found');
}
})
.catch(error => {
console.log(error)
return []
});
};
};
loadMore = (region) => {
console.log(this.state[region])
if(this.state[region])
this.setState(prevState => ({
[region]: {visible: 5}
}))
}
render(){
const handleRegion =(region) =>{
this.filterRegion(region);
if(this.state[region] && this.state[region].open){
this.setState(prevState =>({
[region]: {...prevState[region],
open: false
}
}))
} else {
this.setState(prevState =>({
[region]: {...prevState[region],
open: true
}
}))
}
}
I've been able to set properties on a particular region, i.e. [region].open, but cannot seem to make it work with visible.
EDIT/PROBLEM SOLVED
After some back and forth with Junius, I adjusted my code. What fixed it for me was setting a variable that contained all of the properties per array element that I wanted, adding them to the array, and then setting the entire array as state using the spread operator.
if (!regions) {
console.log('no regions')
return;
}
if(regions)
console.log(regions);
const regionsState = {};
regions.forEach((region, index) => {
if(this.state[region] && this.state[region].countries[0]){
regionsState[region] = { visible: 5, countries: this.state[region].countries, open: false};
} else {
this.filterRegion(region);
regionsState[region] = { visible: 5, countries: [], open: false};
}
});
// set state here outside the foreach function
this.setState((prevState => ({
...regionsState
})))
};
Lastly, I couldn't get the data to initialize properly. At first, I was loading the data on a click, but that's neither ideal nor realistic; running the code in componentDidMount wouldn't fire after the props were loaded. The solution for me was running the function in componentDidUpdate. My state now initializes correctly. Thanks again Junius for the help!
create a new object and add each region to the object as a property.
setDynamicRegions = regions => {
if (!regions) {
return;
}
const regionsState = {};
regions.forEach((item, index) => {
regionsState[item] = { visible: 0 };
});
// this.setState({
// regionsState: regionsState
// });
};
const uniqueRegions = [
"Asia",
"America",
"Europe",
"Africa",
"Oceania",
"Polar"
];
const setDynamicRegions = regions => {
if (!regions) {
return;
}
const regionsState = {};
regions.forEach((item, index) => {
regionsState[item] = { visible: 0 };
});
// this.setState({
// regionsState: regionsState
// });
console.log(regionsState);
};
setDynamicRegions(uniqueRegions);