im trying to display weather icons from open weather map api , but am not entirely sure how to do it , here is the documentation https://openweathermap.org/weather-conditions .. im passing in weather.icon just like its written in the docs but its not working for some reason ,can someone please tell me what i am doing wrong? thanks
app.js
class App extends React.Component {
state = {
temperature: undefined,
city: undefined,
country: undefined,
pressure: undefined,
humidity: undefined,
description: undefined,
rain:undefined,
icon:undefined,
error: undefined
}
handlenum1Change (evt) {
let temp = (evt.target.value);
}
getWeather = async (e) => {
e.preventDefault();
const city = e.target.city.value;
const api_call = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=metric`);
const data = await api_call.json();
console.log(data)
if (city) {
this.setState({
temperature: data.main.temp,
city: data.name,
icon: data.weather.icon,
rain: data.rain,
pressure: data.main.pressure,
humidity: data.main.humidity,
description: data.weather[0].description,
error: ""
});
} else {
this.setState({
temperature: undefined,
city: undefined,
country: undefined,
humidity: undefined,
description: undefined,
pressure:undefined,
rain : undefined,
error: "Please enter the values."
});
}
}
render() {
return (
<div>
<div className="wrapper">
<div className="main">
<div className="container">
<div className="row">
<div className="col-xs-5 title-container">
</div>
<div className="col-xs-7 form-container">
<form onSubmit={this.getWeather} >
<input type="text" name="city" onChange={this.handlenum1Change} placeholder="City..."/>
<button>Get Weather</button>
</form>
<Weather
temperature={this.state.temperature}
humidity={this.state.humidity}
city={this.state.city}
pressure={this.state.pressure}
description={this.state.description}
rain={this.state.rain}
icon={this.state.icon}
error={this.state.error}
/>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
};
export default App;
weather.js
import React from 'react';
import PropTypes from 'prop-types';
const Weather = props =>
<div>
<p>{props.city}</p>
<p> humidity {props.humidity }</p>
<p> {props.description} </p>
<p> temperature {props.temperature}</p>
<p> atmospheric pressure : {props.pressure}</p>
<p> atmospheric pressure : {props.rain}</p>
<img className="img-fluid" src={props.icon} />
</div>
export default Weather;
In order for you to display the icon, you need to use the URL and not just icon value. Something like this
The value returned from the API is '09d'. So you will have to append the URL with string url to have the weather api url appended with image and image extension.
{http://openweathermap.org/img/w/${props.icon}.png}
Few other things noticed in your code is ,
You are setting default values as undefined, which is not correct.
Please use proper value, something like
state = {
temperature: '',
city: ''
}
https://codesandbox.io/s/6102m4kn3r
as per your code in weather.js
<img src ={`http://openweathermap.org/img/w/${this.props.icon}.png`} alt="wthr img" />
it will display the weather icon...ie
import React, { Component } from 'react';
class Weather extends Component {
render() {
return (
<div>
<p>WeatherNow:
<img src ={`http://openweathermap.org/img/w/${this.props.icon}.png`}
alt="wthr img" />
</p>
</div>
);
}
}
export default Weather;
You have to make change in src attribute of <img>.
As given in Weathermap api you have to request icon by http://openweathermap.org/img/w/10d.png.
Replace 10d.png by props.icon+'.png'. It will work.
In order for you to display the icon, you need to use the URL. Something like the below code
<img src={`http://openweathermap.org/img/w/${data.weather[0].icon}.png`} height="70px" />
Related
I'm trying to render google map on my react-redux app. Everything was was working fine. Until when I decided to add some custom markers to the rendered google map. Now the page is blank because of this error I see in my browser console
lat_lng.js:21 Uncaught Error: Invalid LatLng object: (37.42216, undefined)
at new e (lat_lng.js:21:1)
at O.convert (lat_lng.js:5:1)
at t.fromLatLngToCenterPixel (index.js:43:1)
I quickly reverted back to the working codes....but it still displays the same error.
These are the relevant codes:
locationPin.js
import { Icon } from '#iconify/react'
import locationIcon from '#iconify/icons-mdi/map-marker'
const LocationPin = ({ text }) => (
<div className="pin">
<Icon icon={locationIcon} className="pin-icon" />
<p className="pin-text">{text}</p>
</div>
)
export default LocationPin;
Map.js
import GoogleMapReact from 'google-map-react'
import LocationPin from './LocationPin';
import { MapContainer } from './style';
const Map = ({ location, zoomLevel }) => {
console.log('location', location);
console.log('zoomLevel', zoomLevel);
return (
<MapContainer>
<GoogleMapReact
bootstrapURLKeys= {{ key: process.env.REACT_APP_API_KEY }}
defaultCenter={location}
defaultZoom={zoomLevel}
>
<LocationPin
lat={location.lat}
long={location.long}
text={location.address}
/>
</GoogleMapReact>
</MapContainer>
)
}
export default Map;
ReservationsDetails.js
import Map from "../../components/map/Map";
import ParkingGridVertical from "../../components/ParkingGridVertical";
import { ParkingGridVerticalWrapper, ReservationsAsideWrapper,
ReservationsDetailsContainer,
ReservationsMainWrapper,
ReservationTypeWrapper,
SearchReservationsWrapper,
SearchResultWrapper,
} from "./style";
const ReservationsDetails = () => {
const reserveParking = [
'https://user-images.githubusercontent.com/51296741/169976664-533d9594-fb24-4e81-b097-ee16fbfe9189.png',
'https://user-images.githubusercontent.com/51296741/169976664-533d9594-fb24-4e81-b097-ee16fbfe9189.png',
'https://user-images.githubusercontent.com/51296741/169976664-533d9594-fb24-4e81-b097-ee16fbfe9189.png',
];
const location = {
address: '1600 Amphitheatre Parkway, Mountain View, california.',
lat: 37.42216,
long: -122.08427,
}
console.log('locationMe', location);
return (
<ReservationsDetailsContainer>
<ReservationsAsideWrapper>
<SearchReservationsWrapper>
<ReservationTypeWrapper>
<p>Single Day</p>
<p>Flex</p>
<p>Monthly</p>
</ReservationTypeWrapper>
<SearchResultWrapper>
<input
type="text"
name="search"
placeholder="Search Address, Place and Event"
/>
<button type="submit">Search</button>
</SearchResultWrapper>
</SearchReservationsWrapper>
<ParkingGridVerticalWrapper>
<ParkingGridVertical
locations={reserveParking}
/>
</ParkingGridVerticalWrapper>
</ReservationsAsideWrapper>
<ReservationsMainWrapper>
<Map location={location} zoomLevel={17} />
</ReservationsMainWrapper>
</ReservationsDetailsContainer>
);
}
export default ReservationsDetails;
Any idea on how to fix this will be appreciated.
All I needed to do was to replace long with lng every where in the above components. And it worked...
Example
long={location.long}
to
lng={location.lng}
I have created object like that
export const homeObjOne ={
lightBg: false,
lightText: true,
lightTextDesc: true,
topLine:'Explore DrukBox', // - working correctly
headLine: 'Unlimited printing <br> with us',
description: 'Lets <br> begin!', // - output: Lets <br> begin!(with br)
buttonLabel: 'Get Started',
imgStart: '',
img: './assets/svg-1.svg',
alt: 'DrukBox'
}
and bringing it to component like that
function HeroSection({
lightBg,topLine,lightText,lightTextDesc,headLine,description,buttonLabel,img, alt, imgStart
}) {
return (
<div className={lightBg ? 'home__hero-section' : 'home__hero-section darkBg'}>
<div className="container">
<div className="row home__hero-row"
style={{display:'flex',flexDirection: imgStart === 'start' ? 'row-reverse' : 'row'}}
>
And so on
<div className="home__hero-img-wrapper">
<img src={img} alt={alt}/>
</div>
</div>
</div>
</div>
)
}
but in the object my html code not parses i tried all types ',",`
import {homeObjOne} from './Data'
function Home() {
return (
<div>
<HeroSection {...homeObjOne} />
</div>
)
}
export default Home
thats how i import object
You have created addPagesObjOne as a JS Object.
To access the properties within this object and assuming addPagesObjOne has been:
Imported into the component with your JSX or
Within the component file
Then to correctly reference a property see this example:
<img src={img} alt={alt}/>
will become
<img src={addPagesObjOne.img} alt={addPagesObjOne.alt}/>
Update:
I can see that you have provided an update to how you have laid out your code, I created a quick sandbox here your code works fine. Maybe your assest is not in the correct place?
I would be glad to have some help from you: I added 'react-places-autocomplete' to my app and i'm having an issue with getting some data.
I have a form with several inputs where we can search for a city.
On the first input, i'm looking for a city called "toulouse", and i click on the suggestion:
it displays the right data on top of the search bar, but on the console, the name is ok but coordinates are null.
Still on first input, i'm now looking for a city called "bordeaux", and i click on the suggestion:
it still displays the right data on top of the search bar, but on the console, it displays the name 'bordeaux', but the PREVIOUS coordinates from 'Toulouse'!
Do you have an idea why?
Thank you very much for your help!
Here is the Search Component
import React, { useState, useContext } from 'react';
import PlacesAutocomplete, {
geocodeByAddress,
getLatLng,
} from 'react-places-autocomplete';
import CitiesContext from './CitiesContext';
export default function Search(props) {
const { cities, updateCities } = useContext(CitiesContext);
const [address, setAddress] = useState('');
const [coordinates, setCoordinates] = useState({
lat: null,
lng: null,
});
const handleSelect = async value => {
const results = await geocodeByAddress(value);
// we save the lat and long from the 1st result/ selected one
const latLng = await getLatLng(results[0]);
// Updating coordinates
setCoordinates(latLng);
// Updating address
setAddress(value);
const city = {
name: value,
coordinates,
};
updateCities(city);
console.log('Here is the city: ', city); // Name is OK, but coordinates are the previous ones !
};
return (
<div>
<PlacesAutocomplete
value={address}
onChange={setAddress}
onSelect={handleSelect}
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<p>
latitude: {coordinates.lat} - longitude: {coordinates.lng}
</p>
<p>address: {address}</p>
<input {...getInputProps({ placeholder: props.placeholder })} />
<div>
{loading ? <div>Loading...</div> : null}
{suggestions.map(suggestion => {
const style = {
backgroundColor: suggestion.active ? '#41b6e6' : '#fff',
};
return (
<div {...getSuggestionItemProps(suggestion, { style })}>
{suggestion.description}
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
</div>
);
}
```
I am using react for the front end of a search application.
When user submits a query and a list of results pop up, each with a button that says "Learn More". When the "Learn More" button is pressed, the list of results should all disappear and be replaced with the information on that topic that was selected.
The search bar above should stay in place, if a user searches new information, the learn more info should go away and the new list of results should appear.
I am having trouble displaying the learn more information.
The biggest issue I am having is that I have to use the form with the onSubmit function and as soon as the onSubmit function is called my results will stay for a few seconds and then everything will disappear.
The following shows the parts of my file related to the issue
class Search extends React.Component {
learnMore(obj){
//Here is where i would like to replace the results class with the learn more info. obj.learnMore has the info stored
}
render() {
return (
<div className="search">
<div className="search-bar">
// Here is where my search bar is, results of search get added to results array
</div>
<div className= "results">
{this.state.results.map((obj) =>
<div key={obj.id}>
<p> {obj.name} </p>
<form id= "learn-more-form" onSubmit={() => {this.learnMore(obj); return false;}}>
<input type="submit" value="Learn More"/>
</form>
</div>
)}
</div>
</div>
);
}
}
There are many ways to handle this scenario. In this case, I recommend separating containers from components. The container will handle all things state and update its children components accordingly.
Please note that this example uses a lot of ES6 syntaxes. Please read the following to understand how some of it works: fat arrow functions, ES6 destruction, spread operator, ternary operator, class properties, a controlled react form utilizing event handlers and state, array filtering, and type checking with PropTypes.
It's a lot to take in, so if you have any questions, feel free to ask.
Working example:
containers/SeachForm
import React, { Component } from "react";
import moment from "moment";
import LearnMore from "../../components/LearnMore";
import Results from "../../components/Results";
import SearchBar from "../../components/Searchbar";
const data = [
{
id: "1",
name: "Bob",
age: 32,
email: "bob#example.com",
registered: moment("20111031", "YYYYMMDD").fromNow(),
description: "Bob is a stay at home dad."
},
{
id: "2",
name: "Jane",
age: 43,
email: "jane#example.com",
registered: moment("20010810", "YYYYMMDD").fromNow(),
description: "Jane is a CEO at Oracle."
},
{
id: "3",
name: "Yusef",
age: 21,
email: "yusef#example.com",
registered: moment("20180421", "YYYYMMDD").fromNow(),
description: "Yusef is a student at UC Berkeley."
},
{
id: "4",
name: "Dasha",
age: 29,
email: "dasha#example.com",
registered: moment("20050102", "YYYYMMDD").fromNow(),
description: "Dasha is an owner of a local antique shop."
},
{
id: "5",
name: "Polina",
age: 18,
email: "dasha#example.com",
registered: moment("20190102", "YYYYMMDD").fromNow(),
description: "Polina works at a local movie theather."
}
];
const initialState = {
searchQuery: "",
results: data, // <== change this to an empty array if you don't want to show initial user data
learnMore: false
};
class SearchForm extends Component {
state = { ...initialState }; // spreading out the initialState object defined above; it'll be the same as: "state = { searchQuery: "", results: data, learnMore: false }; "
handleSubmit = e => {
e.preventDefault(); // prevents a page refresh
if (!this.state.searchQuery) return null; // prevents empty search submissions
this.setState({
results: data.filter(
person => person.name.toLowerCase() === this.state.searchQuery.toLowerCase()
) // filters the dataset with the "searchQuery" (lowercased names) and returns the result if it finds a match
});
};
handleSearch = ({ target: { value } }) =>
this.setState({ searchQuery: value }); // updates searchQuery input with an event.target.value
handleReset = () => this.setState({ ...initialState }); // resets to initial state
handleLearnMore = person => {
this.setState({ learnMore: true, results: person }); // sets learnMore to true (to show the "LearnMore" component) and sets results to the selected user
};
render = () => (
<div className="container">
<SearchBar
handleReset={this.handleReset}
handleSearch={this.handleSearch}
handleSubmit={this.handleSubmit}
searchQuery={this.state.searchQuery}
/>
{!this.state.learnMore ? ( // if learnMore is false, then show "Results"
<Results
results={this.state.results}
handleLearnMore={this.handleLearnMore}
/>
) : (
<LearnMore {...this.state.results} /> // otherwise, show LearnMore
)}
</div>
);
}
export default SearchForm;
components/SearchBar
import React from "react";
import PropTypes from "prop-types";
const SearchBar = ({
handleReset,
handleSearch,
handleSubmit,
searchQuery
}) => (
<div className="search">
<div className="search-bar">
<form onSubmit={handleSubmit}>
<input
type="text"
className="uk-input"
value={searchQuery}
placeholder="Search for a name"
onChange={handleSearch}
/>
<div className="button-container">
<button
type="button"
className="uk-button uk-button-danger reset"
onClick={handleReset}
>
Reset
</button>
<button type="submit" className="uk-button uk-button-primary submit">
Submit
</button>
</div>
</form>
</div>
</div>
);
SearchBar.propTypes = {
handleReset: PropTypes.func.isRequired,
handleSearch: PropTypes.func.isRequired,
handleSubmit: PropTypes.func.isRequired,
searchQuery: PropTypes.string
};
export default SearchBar;
components/Results
import React from "react";
import PropTypes from "prop-types";
const Results = ({ handleLearnMore, results }) => (
<div className="results">
{results && results.length > 0 ? (
results.map(person => (
<div key={person.id} className="uk-card uk-card-default uk-width-1-2#m">
<div className="uk-card-header">
<div className="uk-width-expand">
<h3 className="uk-card-title uk-margin-remove-bottom">
{person.name}
</h3>
</div>
</div>
<div className="uk-card-body">
<p>{person.description}</p>
</div>
<div className="uk-card-footer">
<button
onClick={() => handleLearnMore(person)}
className="uk-button uk-button-text"
>
Learn More
</button>
</div>
</div>
))
) : (
<div className="uk-placeholder">No users were found!</div>
)}
</div>
);
Results.propTypes = {
handleLearnMore: PropTypes.func.isRequired,
results: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string,
name: PropTypes.string,
age: PropTypes.number,
email: PropTypes.string,
registered: PropTypes.string,
description: PropTypes.string
})
)
};
export default Results;
components/LearnMore
import React from "react";
import PropTypes from "prop-types";
const LearnMore = ({ name, email, age, description, registered }) => (
<div className="uk-card uk-card-default uk-card-body">
<h3 className="uk-card-header">{name}</h3>
<p>
<strong>Email</strong>: {email}
</p>
<p>
<strong>Registered</strong>: {registered}
</p>
<p>
<strong>Age</strong>: {age}
</p>
<p>
<strong>Job</strong>: {description}
</p>
</div>
);
LearnMore.propTypes = {
name: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
registered: PropTypes.string.isRequired,
description: PropTypes.string.isRequired
};
export default LearnMore;
You should do your onSubmit like this:
<form id= "learn-more-form" onSubmit={this.learnMore(obj)}>
<input type="submit" value="Learn More"/>
</form>
Then the function should be:
learnMore = (data) => (e) => {
e.preventDefault()
console.log(data) // probably setState with this data so you can display it when it, like this.setState({ currentMoreResults: data })
}
After following one of tutorials and playing with the code, I got my weather app working. I also get a nice error message if I don’t enter any value and press the button, but if I enter “wrong” value (city is not in API’s database), the app crashes. Is there any chance I could have something like live input search field? For example, if I start typing ''MA…" only cities with those two first letters will appear and I can click on any of them? Also, another problem is that there are some cities with the same name, so I would really need that live search option. If that is too difficult, how could I just stop my app from crashing if city is not in API’s database?
import React from 'react';
import Titles from "./components/Titles";
import Form from "./components/Form";
import Weather from "./components/Weather";
const API_KEY = "7b31fc51d965595f7ad494ff430bf91f";
class App extends React.Component {
state = {
temperature: undefined,
city: undefined,
country: undefined,
humidity: undefined,
pressure: undefined,
description: undefined,
error: undefined
}
getWeather = async (e) => {
e.preventDefault();
const city = e.target.elements.city.value;
const api_call = await
fetch(`http://api.openweathermap.org/data/2.5/weather?q=${city}&APPID=${API_KEY}&units=metric`);
const data = await api_call.json();
if (city) {
this.setState({
temperature: data.main.temp,
city: data.name,
country: data.sys.country,
humidity: data.main.humidity,
pressure: data.main.pressure,
description: data.weather[0].description,
error: ""
});
} else {
this.setState({
temperature: undefined,
city: undefined,
country: undefined,
humidity: undefined,
pressure: undefined,
description: undefined,
error: "Please enter values..."
});
}
}
render() {
return (
<div>
<div className="wrapper">
<div className="main">
<div className="container">
<div className="row">
<div className="col col-xs-6 col-sm-6 col-md-6 col-lg-6 col-xl-6 title-container">
<Titles />
</div>
<div className="col col-xs-6 col-sm-6 col-md-6 col-lg-6 col-xl-6 form-container">
<Form getWeather={this.getWeather}/>
<Weather
temperature={this.state.temperature}
city={this.state.city}
country={this.state.country}
humidity={this.state.humidity}
pressure={this.state.pressure}
description={this.state.description}
error={this.state.error}
/>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
};
export default App;