使用props

时间:2018-03-21 20:48:08

标签: reactjs

我正在使用谷歌地图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;

1 个答案:

答案 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',
    });
}