Reputation: 97
I am building a weather app.
The behavior would be to have a Button in my main menu. This Button should display the current weather. When clicking this button it should display a card with all the weather informations. This is pretty similar to Momentum
I could successfully create my Weather Card displaying the current Weather and also the forecast.
My issue is I do not know how to display the weather in my button before I click on it to display weather. Not sure how to access my data and render it.
My SideMenu component displaying the Menu
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>);
}
}
The Weather Card component where I get the data from the API and render it
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;
Upvotes: 0
Views: 89
Reputation: 1533
You can control the display of you widget using the state.
You can pass a click handler
to your sidemenu
as a prop, once you click on an item you emit the click event to the parent component (with some payload if you want).
The parent component will have a handler method which is responsible for displaying your widget.
I've made some adjustments into you index.js
and SideMenu.js
files.
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>
);
}
}
here is a fully working stacklitz with the adjustments mentioned above, hope that this will help.
If you want a data to be accessible by all the components, then you have these options:
Redux or MobX which are state management libraries.
Upvotes: 1