从父组件状态获取道具以渲染数据

时间:2019-04-06 13:10:33

标签: reactjs

我正在构建一个天气应用程序。 行为是在我的主菜单中有一个按钮。此按钮应显示当前天气。单击此按钮时,它将显示一张包含所有天气信息的卡片。这与动量https://momentumdash.com/

非常相似

我可以成功创建显示当前天气以及天气预报的天气卡。(/home/starke/Screenshot from 2019-04-06 14-57-35.png

我的问题是在单击按钮显示天气之前,我不知道如何在按钮中显示天气。不确定如何访问我的数据并呈现它。

我的SideMenu组件显示菜单

export default class SideMenu extends React.Component {
    constructor(props) {
        super(props);
    }

    changeView(e, view) {
      e.preventDefault();
      this.props.changeView(view);
    }

    render() {
      const { cityName } = this.props;
            return (<Menu>
              <Button onClick={(e) => this.changeView(e, "weather")}>
              </Button>
              <Button onClick={(e) => this.changeView(e, "todo")}>
                ToDo
              </Button>
              <Button onClick={(e) => this.changeView(e, "pomodoro")}>
                Pomo
              </Button>
              <Button onClick={(e) => this.changeView(e, "picture")}>
                Info
              </Button>
            </Menu>);
    }
}


天气卡组件,我可以从API中获取数据并进行渲染

class WeatherCard extends Component {
  constructor(props) {
    super(props);

    this.state = {
      temperature: "",
      latitude: "",
      longitude: "",
      summary: "",
      cityName: "",
      numForecastDays: 5,
      isLoading: false
    };
  }

  componentDidMount() {
    this.getLocation();
  }

  // Use of APIXU API with latitude and longitude query
  getWeather() {
    const { latitude, longitude, numForecastDays } = this.state;
    const URL = `https://api.apixu.com/v1/forecast.json?key=${KEY}&q=${latitude},${longitude}&days=${numForecastDays}`;
    axios
      .get(URL)
      .then(res => {
        const data = res.data;

        this.setState({
          cityName: data.location.name + ", " + data.location.region,
          summary: data.current.condition.text,
          temperature: data.current.temp_c,
          forecastDays: data.forecast.forecastday,
          iconURL: data.current.condition.icon
        });
      })
      .catch(err => {
        if (err) console.log(err);
      });
  }

  // function using current longitude and latitude of user
  // This requires authorization from user // Could be changed using IP adress instead, but would be less precise
  getLocation() {
    navigator.geolocation.getCurrentPosition(
      position => {
        this.setState(
          prevState => ({
            latitude: position.coords.latitude,
            longitude: position.coords.longitude
          }),
          () => {
            this.getWeather();
          }
        );
      },
      error => this.setState({ forecast: error.message }),
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
    );
  }
  render() {
    const {
      summary,
      temperature,
      cityName,
      iconURL,
      forecastDays,
      isLoading
    } = this.state;
    return (
      <div>
        {isLoading && (
          <div>
            <Spinner />
            <LoaderText>Loading....</LoaderText>
          </div>
        )}
        {!isLoading && (
          <Wrapper>
            <CurrentWeather
              cityName={cityName}
              summary={summary}
              temperature={temperature}
              icon={iconURL}
            />
            <Forecast forecastDays={forecastDays} />
          </Wrapper>
        )}
      </div>
    );
  }
}

export default WeatherCard;

1 个答案:

答案 0 :(得分:1)

您可以使用状态控制小部件的显示。

您可以将点击handler传递给sidemenu作为道具,一旦您单击某个项目,就会将点击事件发送给父级组件(带有一些有效负载)如果需要的话。

父组件将具有一个处理程序方法,负责显示您的小部件。

我对您的index.jsSideMenu.js文件进行了一些调整。

index.js

import React, { Component } from 'react';
import { render } from 'react-dom';
import WeatherCard from './Weather';
import SideMenu from './SideMenu';

class App extends Component {
  constructor() {
    super();
    this.state = {
      showWeather: false
    }
  }

  handleItemClick = (item) => {
    if (item === 'weather') {
       this.setState({
        showWeather: true
      });
    }
  } 
  render() {
    return (
      <div>
        <SideMenu onItemClick={this.handleItemClick} />
        {this.state.showWeather ? <WeatherCard /> : null}
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

SideMenu.js

export default class SideMenu extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { cityName } = this.props;
    return (
      <Menu>
        <Button onClick={() => this.props.onItemClick('weather')}>
          Open Weather Widget
        </Button>
      </Menu>
    );
  }
}

stacklitz是经过上述调整的完全有效的方法,希望对您有所帮助。

如果希望所有组件都可以访问数据,则可以使用以下选项:

React Context

ReduxMobX是状态管理库。