我的天气应用程序有很大的问题。
我使用的是OpenweatherMap免费API,并且创建了一个包含两个选择输入的页面:一个用于从直接在州内陈述的对象数组中选择一个国家,第二个用于选择城市。
第二个选择非常棘手,因为我上传了一个巨大的JSON文件,其中包含API服务的所有城市的列表,并且我想过滤出不属于先前选择的国家/地区的每个城市。
我的问题是generateCitiesList()
函数不会将经过过滤的元素传递到this.state.cityList
import React from "react";
import ReactDOM from "react-dom";
import CITIES from "./cities.json";
import COUNTRIES from "./countries.json";
import "./styles.css";
// So getCitiesByCountry accepts (country) parameter for which we use
// this.state.selectedCountry and filter how exactly?
// Do we compare every element within cities.json file so that it returns
// an object (array?) that meets the criteria of element.country being equal to
// this.state.selectedCountry?
const getCitiesByCountry = (country) =>
CITIES.filter(city => city.country === country);
//
class App extends React.PureComponent {
state = { selectedCoutnry: "" };
handleOnSelectCountry = e => {
this.setState({ selectedCoutnry: e.target.value });
};
render() {
// What does this line of code do? It looks like an object destructurization
// so should I assume that from now on
// const selectedCountry is equal to this.state.selectedCountry ?
const { selectedCoutnry } = this.state;
return (
<div className="App">
<select value={selectedCoutnry} onChange={this.handleOnSelectCountry}>
<option>Select a Country</option>
// That makes a lot of sense. Why would I store countries list in state
while I could access it via JSON file.
{COUNTRIES.map(({ name, id }) => (
<option value={id} key={id}>
{name}
</option>
))}
</select>
{selectedCoutnry && (
<select>
<option>Select a City</option>
// So we use a function getCitiesByCountry which returns a filtered object
// which is then mapped through to render <option>s?
{getCitiesByCountry(selectedCoutnry).map(({ name, id }) => (
<option value={id} key={id}>
{name}
</option>
))}
</select>
)}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
[ { “ id”:707860, “ name”:“ Hurzuf”, “ country”:“ UA”, “坐标”:{ “ lon”:34.283333, “ lat”:44.549999 } }, { “ id”:519188, “ name”:“ Novinki”, “ country”:“ RU”, “坐标”:{ “ lon”:37.666668, “ lat”:55.683334 } }, { “ id”:1283378, “ name”:“Gorkhā”, “ country”:“ NP”, “坐标”:{ “ lon”:84.633331, “ lat”:28 } } ]
答案 0 :(得分:0)
看看是否适合您。
这代表城市的JSON。
cities: {
city1: {
cityName: 'City1',
country: 'A'
},
city2: {
cityName: 'City2',
country: 'A'
},
city3: {
cityName: 'City3',
country: 'B'
},
city4: {
cityName: 'City4',
country: 'B'
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state={
selectedCountry: 'A',
countries: ['A','B'],
cities: {
city1: {cityName: 'City1',
country: 'A'},
city2: {cityName: 'City2',
country: 'A'},
city3: {cityName: 'City3',
country: 'B'},
city4: {cityName: 'City4',
country: 'B'},
}
}
this.selectCountry = this.selectCountry.bind(this);
}
selectCountry() {
this.setState((prevState) => {
return({
...prevState,
selectedCountry: prevState.selectedCountry === 'A' ? 'B' : 'A'
});
});
}
render() {
let filteredCities = [];
for (let i in this.state.cities) {
this.state.selectedCountry === this.state.cities[i].country ?
filteredCities.push(this.state.cities[i]) : null;
}
filteredCities = filteredCities.map((item)=>
<li>{item.cityName}</li>
);
return(
<React.Fragment>
<div>Selected Country: {this.state.selectedCountry}</div>
<button onClick={this.selectCountry}>Change Country</button>
<div>Country List</div>
<div>
<ul>
{filteredCities}
</ul>
</div>
</React.Fragment>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 1 :(得分:0)
这看起来很邪恶。不要直接改变状态。
generateCitiesList = () => {
const self = this;
self.state.cityList.push(citiesList.filter( function (countries) {
return countries.country === `${self.state.country}`
}));
console.log(this.state.cityList);
this.showCitiesList() ===> WORKS, pushing desired objects into an array
};
将状态填充到生命周期函数componentDidMount
中componentDidMount() {
const cityList = citiesList.filter(element => element.country === this.state.country);
this.setState({cityList});
}
答案 2 :(得分:0)
由于以下原因,您的代码无法正常工作:
citiesArray.push(filterCities)
应写为:
citiesArray.push(...filterCities)
但是您可以通过将代码减少为:
generateCitiesList = () => {
this.setState ({
listCity: citiesList.filter(({country}) => (
country === `${this.state.country}`;
))
});
};
但是,在您的情况下,只应使用状态存储影响视图的最小数据-所选的国家/城市。
当前所选国家/地区的城市列表不能成为州的一部分,因为它可以从所选国家/地区派生。
只需编写一个获取国家/地区的函数,然后返回该国家/地区的城市列表,然后在render()
中针对所选国家/地区运行它即可:
render() {
return (
...
<select>
{getCitiesByCountry(this.state.country).map(city => (
<option value={city}>{city}</option>
))}
</select>
...
);
}
答案 3 :(得分:0)
好吧,感谢@Yoav Kadosh(鸣谢!)我在下面是answear。
事实证明,为了有效地映射选定数量的项目,您应该:
相反,您还可以应用链运算符,例如variable.filter((parameter)=> parameter> 2).map({element} => {element})。
constructor(props) {
super(props);
this.state = {
country: '',
city: '',
result: {
temperature: ''
}
}
}
handleCountrySelect = (e) => {
this.setState({
country: e.target.value
});
console.log(e.target.value);
};
filterCitiesByCountry = (country) => {
return citiesJSON.filter ( city => city.country === country)
};
handleCitySelect = (e) => {
this.setState ({
city: e.target.value
});
console.log(e.target.value)
};
getWeather = async (e) => {
e.preventDefault();
fetch(`http://api.openweathermap.org/data/2.5/weather?q=${this.state.city},${this.state.country}&appid=${APIKEY}`)
.then( res => res.json())
.then( res =>
this.setState ({
result: {
temperature: Math.round(res.main.temp - 273.15)
}
})
)
};
render() {
return (
<main>
<section className='row text-center' id='weather_select_section'>
<form>
<div className="countrySelect col-12 col-sm-6 text-center mt-5 mb-5 ">
<label> Select Country </label>
<select onChange={this.handleCountrySelect} required placeholder='Country...'>
<option value='' data-index='Country...'> </option>
{ countriesJSON.map(({name, code, key} ) => {
return (
<option value={code} key={key} > {name} </option>
)
})}
</select>
</div>
<div className="citySelect col-12 col-sm-6 text-center mt-5 mb-5 ">
<label> Select City </label>
{this.state.country && (
<select onChange={this.handleCitySelect} placeholder='City...' required>
<option value='' data-index='City...'></option>
{ this.filterCitiesByCountry(this.state.country).map(({name, key}) =>
<option value={name} key={key}> {name} </option>
)}
</select>
)
}
</div>
<button type='submit' onClick = {this.getWeather} className=" col-10 mt-5 mb-5 text-center "> Get Weather</button>
</form>
<div className=" col-12 WeatherInfoBox ">
<h3> Weather in {this.state.city}</h3>
<p> {this.state.result.temperature} ℃</p>