如何在设置之前停止将状态元素传递给子组件?
How do I stop state element being passed to child component before it is set?
我正在用 React 编写一个天气预报应用程序。我正在从 openweathermap.org API 获取数据。但是要使用它,我需要知道用户的位置。所以我也依次使用其他 API 来识别用户 IP、位置,然后根据该位置识别天气数据。在每个获取状态,我都会用获取的信息更新初始状态。例如,当我获取 Ip 时,我使用 setState 更新状态中的 userIP,然后当获取纬度和经度时,我也更新 userLat 和 userLng。因此,states 中的 weatherData 最初是一个空数组,是最后一个被更新的。问题是,每次更改其中一个状态时,渲染都是 运行。由于我将 weatherData 作为道具传递给的子组件之一使用了该获取的 weatherData 数组中的一个对象,因此我收到一个错误,因为直到 weatherData 更新,渲染 运行s 并将一个空数组传递给它零件。我尝试使用 if 语句在返回结果之前检查 weatherData 是否为空数组,但不知何故它不起作用。
这是我的 App.js 文件:
import React, {Component} from 'react';
import './App.css';
import Mainblock from './Mainblock';
import Hourly from './Hourly';
import Weekly from './Weekly';
class App extends Component {
constructor() {
super()
this.state = {
userIp: 0,
cityName: '',
cityNameNoSpace: '',
userLat: 0,
userLng: 0
}
}
componentDidMount(){
fetch("https://geoip-db.com/json/").then((data)=> {
return data.json();
}).then((ip)=>{
this.setState({userIp: ip.IPv4});
this.locateClient(this.state.userIp);
});
}
locateClient = (clientIp) => {
fetch(`https://ip-geolocation.whoisxmlapi.com/api/v1?apiKey=at_SECRETAPIKEY&ipAddress=${clientIp}`).then((data)=>{
return data.json();
}).then((locationInfo)=>{
this.setState({userLat: locationInfo.location.lat, userLng: locationInfo.location.lng, cityName: locationInfo.location.city});
let cityArray = Array.from(locationInfo.location.city);
let cityNameFiltered = '';
cityArray.forEach((letter)=>{
cityNameFiltered = cityNameFiltered + letter;
return cityNameFiltered;
})
this.setState({cityNameNoSpace: cityNameFiltered});
this.getWeatherData(this.state.cityNameNoSpace);
});
}
getWeatherData = (userCity) => {
fetch(`https://api.openweathermap.org/data/2.5/onecall?lat=${this.state.userLat}&lon=${this.state.userLng}&units=metric&appid=SECRETAPIKEY`).then((data)=>{
return data.json();
}).then((weatherInfo)=>{
this.setState({weatherData: weatherInfo});
});
}
render() {
return (
<div className="whole-container">
<div className="lside">
<Mainblock states={this.state}/>
<Weekly />
</div>
<Hourly />
</div>
);
}
}
export default App;
由于您的 Mainblock
组件期望 states 道具是一个带有 属性 weatherData 的对象,其中 weatherData 应该是一个数组,您可以 conditionally render 该组件。
有条件地渲染它看起来像下面这样:
render() {
return (
<div className="whole-container">
<div className="lside">
{Array.isArray(this.state.weatherData) && <Mainblock states={this.state}/> }
<Weekly />
</div>
<Hourly />
</div>
);
}
之所以有效,是因为 javascript 计算布尔表达式,returns 表达式的右侧为 true,否则返回 false。
> true && 123
< 123
> false && 123
< false
我正在用 React 编写一个天气预报应用程序。我正在从 openweathermap.org API 获取数据。但是要使用它,我需要知道用户的位置。所以我也依次使用其他 API 来识别用户 IP、位置,然后根据该位置识别天气数据。在每个获取状态,我都会用获取的信息更新初始状态。例如,当我获取 Ip 时,我使用 setState 更新状态中的 userIP,然后当获取纬度和经度时,我也更新 userLat 和 userLng。因此,states 中的 weatherData 最初是一个空数组,是最后一个被更新的。问题是,每次更改其中一个状态时,渲染都是 运行。由于我将 weatherData 作为道具传递给的子组件之一使用了该获取的 weatherData 数组中的一个对象,因此我收到一个错误,因为直到 weatherData 更新,渲染 运行s 并将一个空数组传递给它零件。我尝试使用 if 语句在返回结果之前检查 weatherData 是否为空数组,但不知何故它不起作用。
这是我的 App.js 文件:
import React, {Component} from 'react';
import './App.css';
import Mainblock from './Mainblock';
import Hourly from './Hourly';
import Weekly from './Weekly';
class App extends Component {
constructor() {
super()
this.state = {
userIp: 0,
cityName: '',
cityNameNoSpace: '',
userLat: 0,
userLng: 0
}
}
componentDidMount(){
fetch("https://geoip-db.com/json/").then((data)=> {
return data.json();
}).then((ip)=>{
this.setState({userIp: ip.IPv4});
this.locateClient(this.state.userIp);
});
}
locateClient = (clientIp) => {
fetch(`https://ip-geolocation.whoisxmlapi.com/api/v1?apiKey=at_SECRETAPIKEY&ipAddress=${clientIp}`).then((data)=>{
return data.json();
}).then((locationInfo)=>{
this.setState({userLat: locationInfo.location.lat, userLng: locationInfo.location.lng, cityName: locationInfo.location.city});
let cityArray = Array.from(locationInfo.location.city);
let cityNameFiltered = '';
cityArray.forEach((letter)=>{
cityNameFiltered = cityNameFiltered + letter;
return cityNameFiltered;
})
this.setState({cityNameNoSpace: cityNameFiltered});
this.getWeatherData(this.state.cityNameNoSpace);
});
}
getWeatherData = (userCity) => {
fetch(`https://api.openweathermap.org/data/2.5/onecall?lat=${this.state.userLat}&lon=${this.state.userLng}&units=metric&appid=SECRETAPIKEY`).then((data)=>{
return data.json();
}).then((weatherInfo)=>{
this.setState({weatherData: weatherInfo});
});
}
render() {
return (
<div className="whole-container">
<div className="lside">
<Mainblock states={this.state}/>
<Weekly />
</div>
<Hourly />
</div>
);
}
}
export default App;
由于您的 Mainblock
组件期望 states 道具是一个带有 属性 weatherData 的对象,其中 weatherData 应该是一个数组,您可以 conditionally render 该组件。
有条件地渲染它看起来像下面这样:
render() {
return (
<div className="whole-container">
<div className="lside">
{Array.isArray(this.state.weatherData) && <Mainblock states={this.state}/> }
<Weekly />
</div>
<Hourly />
</div>
);
}
之所以有效,是因为 javascript 计算布尔表达式,returns 表达式的右侧为 true,否则返回 false。
> true && 123
< 123
> false && 123
< false