我正在使用谷歌地图api创建一个简单的天气api,我差不多完成了。但是,当我创建Google地图时,我需要将Lat和Long道具传递给我的子组件功能。我成功地将状态传递给子组件。但是,在我的子组件中,我有另一个包含我的谷歌代码的功能。当我尝试插入它的lat,lng坐标到API时,它返回0,0原因是我没有访问这个子组件功能中的道具。但是,我可以访问返回和渲染中的道具。
所以我的问题是如何从父组件访问子组件功能中的道具?
父组件
这是我的代码:
/*eslint-disable no-unused-vars*/
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Weathermodule from './weatherModule';
class Weather extends React.Component {
constructor(props){
super(props);
this.state = {
city: '',
state: '',
country: '',
weatherCity: '',
weatherState: '',
weatherLongitude: '',
weatherLatitude: '',
weatherDays: [],
weatherDate: [],
weatherIcons: [],
weatherAlt: [],
weatherTemp: [],
weatherpresentTemp: [],
errors: '',
showweatherComponent: false,
}
}
onChange(e){
this.setState({
[e.target.name]: e.target.value
})
}
async onSubmit(e){
e.preventDefault();
const APIkey = 'hiddenfortest';
const city = this.state.city;
const state = this.state.state;
const country = this.state.country;
if(this.state.city === '' || this.state.state === '') {
this.setState({errors: 'Please fill out all required fields.'})
} else {
this.setState({
showweatherComponent: true,
});
const res = await fetch(`http://api.wunderground.com/api/${APIkey}/forecast/geolookup/conditions/q/${country}/${state}/${city}.json`);
const json = await res.json();
// For logging response
// console.log(json);
this.setState({
weatherCity: json.location.city,
weatherState: json.location.state,
weatherLatitude: json.location.lat,
weatherLongitude: json.location.lon,
weatherZip: json.location.zip,
// Weather Days ex. Tuesday, Wednesday, Thursday etc..
weatherDays: [
json.forecast.simpleforecast.forecastday[0].date.weekday,
json.forecast.simpleforecast.forecastday[1].date.weekday,
json.forecast.simpleforecast.forecastday[2].date.weekday,
json.forecast.simpleforecast.forecastday[3].date.weekday,
],
// Weather Dates
weatherDate: [
json.forecast.simpleforecast.forecastday[0].date.month,
json.forecast.simpleforecast.forecastday[0].date.day,
json.forecast.simpleforecast.forecastday[1].date.month,
json.forecast.simpleforecast.forecastday[1].date.day,
json.forecast.simpleforecast.forecastday[2].date.month,
json.forecast.simpleforecast.forecastday[2].date.day,
json.forecast.simpleforecast.forecastday[3].date.month,
json.forecast.simpleforecast.forecastday[3].date.day,
],
// Weather Icons generated for the weather dates
weatherIcons: [
json.forecast.simpleforecast.forecastday[0].icon_url,
json.forecast.simpleforecast.forecastday[1].icon_url,
json.forecast.simpleforecast.forecastday[2].icon_url,
json.forecast.simpleforecast.forecastday[3].icon_url,
],
// Weather Alt Attributes appended to the jsx img tag
weatherAlt: [
json.forecast.simpleforecast.forecastday[0].icon,
json.forecast.simpleforecast.forecastday[1].icon,
json.forecast.simpleforecast.forecastday[2].icon,
json.forecast.simpleforecast.forecastday[3].icon,
],
// High/Low Fahrenheit temperature for the weather dates
weatherpresentTemp: [
json.forecast.simpleforecast.forecastday[0].high.fahrenheit,
json.forecast.simpleforecast.forecastday[0].low.fahrenheit,
json.forecast.simpleforecast.forecastday[1].high.fahrenheit,
json.forecast.simpleforecast.forecastday[1].low.fahrenheit,
json.forecast.simpleforecast.forecastday[2].high.fahrenheit,
json.forecast.simpleforecast.forecastday[2].low.fahrenheit,
json.forecast.simpleforecast.forecastday[3].high.fahrenheit,
json.forecast.simpleforecast.forecastday[3].low.fahrenheit,
],
// Today temperature fahrenheit, and celsius
weatherTemp: [
json.current_observation.temp_f,
json.current_observation.temp_c,
]
})
// console.log(this.state);
}
}
render(){
const latitude = parseFloat(this.state.weatherLatitude).toFixed(2) === NaN ? '' : parseFloat(this.state.weatherLatitude).toFixed(2)
const longitude = parseFloat(this.state.weatherLongitude).toFixed(2) === NaN ? '' : parseFloat(this.state.weatherLongitude).toFixed(2)
return (
<div className="container">
<h1>Weather Demo</h1>
{this.state.errors !== '' ? <p style={{color:'#E2231A'}}>Please fill out all required fields</p> : ''}
<form
method="POST"
onSubmit={e => this.onSubmit(e)}
>
<label>City</label>
<input
type="text"
className="form-control"
name="city"
placeholder="City"
onChange={e => this.onChange(e)}
value={this.state.city}
/>
<label>State</label>
<input
type="text"
className="form-control"
name="state"
placeholder="State"
onChange={e => this.onChange(e)}
value={this.state.state}
/>
<label>Country</label>
<input
type="text"
className="form-control"
name="country"
placeholder="Country"
onChange={e => this.onChange(e)}
value={this.state.country}
/>
<button
type="submit"
className="btn btn-regular"
onClick={e => this.onSubmit(e)}
>
Get Weather
</button>
</form>
{/* Don't show component until submit button clicked, once clicked, pass state down to props for other component */}
{
this.state.showweatherComponent ?
<Weathermodule
city={this.state.city}
state={this.state.state}
country={this.state.country}
weatherCity={this.state.weatherCity}
weatherState={this.state.weatherState}
weatherLongitude={this.state.weatherLongitude}
weatherLatitude={this.state.weatherLatitude}
weatherDays={this.state.weatherDays}
weatherDate={this.state.weatherDate}
weatherIcons={this.state.weatherIcons}
weatherAlt={this.state.weatherAlt}
weatherTemp={this.state.weatherTemp}
weatherpresentTemp={this.state.weatherpresentTemp}
longitude={longitude}
latitude={latitude}
/>
:
null
}
</div>
)
}
}
export default Weather;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
子组件
/*eslint-disable no-unused-vars*/
import React from 'react';
import ReactDOM from 'react-dom';
class Weathermodule extends React.Component {
componentDidMount(){
var locations = {
lat: Number(this.props.weatherLatitude),
lng: Number(this.props.weatherLongitude)
};
console.log(locations);
let map = new window.google.maps.Map(document.getElementById('map'), {
center: locations,
zoom: 13,
mapTypeId: 'roadmap',
});
console.log(this.props);
}
render(){
return (
<div className="container">
<h1>Weather</h1>
<div className="row" id="weather-description">
<div className="col-md-6">
<h2>{this.props.weatherCity}, {this.props.weatherState}</h2>
<img src={this.props.weatherIcons[0]} alt={this.props.weatherAlt[0]} />
<h3>{this.props.weatherTemp[0]}<sup>o</sup>F</h3>
<h4>({this.props.weatherTemp[1]}<sup>o</sup>C)</h4>
</div>
<div className="col-md-6">
<p>Latitude: {this.props.latitude}, Longitude: {this.props.longitude}</p>
<div id="map" className="map-alignment"></div>
</div>
</div>
<div className="row">
<div className="col-md-3" id="red">
<h3>{this.props.weatherDays[0]}</h3>
<p>{this.props.weatherDate[0] + "/" + this.props.weatherDate[1]}</p>
<img src={this.props.weatherIcons[0]} alt={this.props.weatherAlt[0]} />
<p>{this.props.weatherpresentTemp[0]}<sup>o</sup> | {this.props.weatherpresentTemp[1]}<sup>o</sup>F</p>
</div>
<div className="col-md-3" id="blue">
<h3>{this.props.weatherDays[1]}</h3>
<p>{this.props.weatherDate[2] + "/" + this.props.weatherDate[3]}</p>
<img src={this.props.weatherIcons[1]} alt={this.props.weatherAlt[1]} />
<p>{this.props.weatherpresentTemp[2]}<sup>o</sup> | {this.props.weatherpresentTemp[3]}<sup>o</sup>F</p>
</div>
<div className="col-md-3" id="black">
<h3>{this.props.weatherDays[2]}</h3>
<p>{this.props.weatherDate[4] + "/" + this.props.weatherDate[5]}</p>
<img src={this.props.weatherIcons[2]} alt={this.props.weatherAlt[2]} />
<p>{this.props.weatherpresentTemp[4]}<sup>o</sup> | {this.props.weatherpresentTemp[5]}<sup>o</sup>F</p>
</div>
<div className="col-md-3" id="green">
<h3>{this.props.weatherDays[3]}</h3>
<p>{this.props.weatherDate[6] + "/" + this.props.weatherDate[7]}</p>
<img src={this.props.weatherIcons[3]} alt={this.props.weatherAlt[3]} />
<p>{this.props.weatherpresentTemp[6]}<sup>o</sup> | {this.props.weatherpresentTemp[7]}<sup>o</sup>F</p>
</div>
</div>
</div>
)
}
}
export default Weathermodule;
答案 0 :(得分:0)
在onSubmit()
组件的Weather
功能中,您拨打this.setState({showweatherComponent: true,});
,然后调用异步功能获取所有地图数据。
当您第一次调用setState
时,render()
函数条件将呈现您的Weathermodule
组件,其当前状态值将在此时为默认值值,因为您的异步API调用尚未返回数据,而您还没有使用新数据setState。
当您的api调用返回数据并且您已设置状态时,您的Weathermodule
组件早已安装。您没有检查孩子的componentWillReceiveProps
是否应该更新您的地图。
您尝试不在Weathermodule
中使用州,但如果您这样做,则会更容易管理。添加设置地图的功能,而不是直接在compenentDidMount
中设置地图功能。这样,您可以根据需要从生命周期的多个位置调用您的地图功能。
思考你想要解决的方式。您可以在setState()
中更改第一个onSubmit()
来电的展示位置,也可以向您的子组件添加更多生命周期事件,或者两者兼而有之。
在家长
中async onSubmit(e){
e.preventDefault();
const APIkey = 'hiddenfortest';
const city = this.state.city;
const state = this.state.state;
const country = this.state.country;
if(this.state.city === '' || this.state.state === '') {
this.setState({errors: 'Please fill out all required fields.'})
} else {
// no need to start rendering your map until you have data
const res = await fetch(`http://api.wunderground.com/api/${APIkey}/forecast/geolookup/conditions/q/${country}/${state}/${city}.json`);
const json = await res.json();
// For logging response
// console.log(json);
this.setState({
weatherCity: json.location.city,
weatherState: json.location.state,
weatherLatitude: json.location.lat,
weatherLongitude: json.location.lon,
weatherZip: json.location.zip,
// Weather Days ex. Tuesday, Wednesday, Thursday etc..
weatherDays: [
json.forecast.simpleforecast.forecastday[0].date.weekday,
json.forecast.simpleforecast.forecastday[1].date.weekday,
json.forecast.simpleforecast.forecastday[2].date.weekday,
json.forecast.simpleforecast.forecastday[3].date.weekday,
],
// Weather Dates
weatherDate: [
json.forecast.simpleforecast.forecastday[0].date.month,
json.forecast.simpleforecast.forecastday[0].date.day,
json.forecast.simpleforecast.forecastday[1].date.month,
json.forecast.simpleforecast.forecastday[1].date.day,
json.forecast.simpleforecast.forecastday[2].date.month,
json.forecast.simpleforecast.forecastday[2].date.day,
json.forecast.simpleforecast.forecastday[3].date.month,
json.forecast.simpleforecast.forecastday[3].date.day,
],
// Weather Icons generated for the weather dates
weatherIcons: [
json.forecast.simpleforecast.forecastday[0].icon_url,
json.forecast.simpleforecast.forecastday[1].icon_url,
json.forecast.simpleforecast.forecastday[2].icon_url,
json.forecast.simpleforecast.forecastday[3].icon_url,
],
// Weather Alt Attributes appended to the jsx img tag
weatherAlt: [
json.forecast.simpleforecast.forecastday[0].icon,
json.forecast.simpleforecast.forecastday[1].icon,
json.forecast.simpleforecast.forecastday[2].icon,
json.forecast.simpleforecast.forecastday[3].icon,
],
// High/Low Fahrenheit temperature for the weather dates
weatherpresentTemp: [
json.forecast.simpleforecast.forecastday[0].high.fahrenheit,
json.forecast.simpleforecast.forecastday[0].low.fahrenheit,
json.forecast.simpleforecast.forecastday[1].high.fahrenheit,
json.forecast.simpleforecast.forecastday[1].low.fahrenheit,
json.forecast.simpleforecast.forecastday[2].high.fahrenheit,
json.forecast.simpleforecast.forecastday[2].low.fahrenheit,
json.forecast.simpleforecast.forecastday[3].high.fahrenheit,
json.forecast.simpleforecast.forecastday[3].low.fahrenheit,
],
// Today temperature fahrenheit, and celsius
weatherTemp: [
json.current_observation.temp_f,
json.current_observation.temp_c,
],
//now you have data, show your component
showweatherComponent: true
})
在儿童中
componentDidMount(){
var locations = {
lat: Number(this.props.weatherLatitude),
lng: Number(this.props.weatherLongitude)
};
this.renderMap(locations);
}
componentWillReceiveProps(nextProps){
//ideally this is why giving this component state is important
//you only would call renderMap if you received new lat/lon coords
//that is, you would compare state with nextProps
var locations = {
lat: Number(nextProps.weatherLatitude),
lng: Number(nextProps.weatherLongitude)
};
this.renderMap(locations);
}
renderMap = locations => {
let map = new window.google.maps.Map(document.getElementById('map'), {
center: locations,
zoom: 13,
mapTypeId: 'roadmap',
});
}