I have two components where one comp provides a search input field where the user will enter data(e.g; city name) and another comp provides the main weather data( based on the user search input from comp 1) like temp, wind, etc.. how should I pass the user input to the API so it will render the data of that city. I have been stuck on this issue for the last 3 days. any solution?
Comp1 (search comp)
import React, { useState } from "react";
import "../Componentstyle/search.css";
export default function Search() {
const [location, setLocation] = useState();
const handlesubmit = (event)=>{
event.preventDefault();
setLocation(event.target.value)
}
return (
<>
<div className="main">
<nav className="istclass">
<form className="form">
<div className="search">
<input
value={location}
placeholder="search city"
className="searchbox"
onChange={(e) => setLocation(e.target.value)}
/>
<button className="nd" type="button" onClick={handlesubmit}>
Submit
</button>
</div>
</form>
</nav>
</div>
</>
);
}
Comp2 (maindata comp)
import React, { useState, useEffect } from "react";
import "../Componentstyle/Main.css";
export default function Maindata() {
const [data, setData] = useState();
let city = "mansehra";
let weather = async () => {
// if(!city)return;
const key = "XYZ";
await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}&units=metric&formatted=0`
)
.then((response) => response.json())
.then((actualData) => setData(actualData));
};
useEffect(() => {
weather();
}, []);
if (!data) {
return <div>Loading...</div>;
}
const link = `http://openweathermap.org/img/w/${data.weather[0].icon}.png`;
return (
<>
<div className="maindata">
<div className="city">{data.name}</div>
<div className="temp">{data.main.temp} C</div>
<div className="icon">
<img src={link} alt="not found" />{" "}
</div>
<div className="feel">feels Like {data.main.feels_like} C</div>
<div className="wind">Wind {data.wind.speed} Km/hr</div>
<div className="cloudy">{data.weather[0].main}</div>
<div className="humidity">humidity {data.main.humidity}%</div>
<div className="sunrise">
sunrise :- {new Date(data.sys.sunrise * 1000).toUTCString()}{" "}
</div>
<div className="sunset">
sunset :- {new Date(data.sys.sunset * 1000).toUTCString()}
</div>
</div>
</>
);
}
App.js Comp
import "./App.css";
import Maindata from "./Components/Maindata";
import Search from "./Components/Search";
function App() {
return (
<div className="mainpage">
<div className="searchComp">
<Search />
</div>
<div className="details">
<Maindata />
);
}
export default App;
You can simply Lift State Up. Move the Search
component's state up to a common ancestor component and pass the state and state updater callback function down as props to the components needing them.
Example:
App
function App() {
const [location, setLocation] = useState();
return (
<div className="mainpage">
<div className="searchComp">
<Search {...{ location, setLocation }} />
</div>
<div className="details">
<Maindata city={location} />
</div>
</div>
);
}
Search
export default function Search({ location, setLocation }) {
const handlesubmit = (event) => {
event.preventDefault();
setLocation(event.target.value);
};
return (
<div className="main">
<nav className="istclass">
<form className="form">
<div className="search">
<input
value={location}
placeholder="search city"
className="searchbox"
onChange={(e) => setLocation(e.target.value)}
/>
<button className="nd" type="button" onClick={handlesubmit}>
Submit
</button>
</div>
</form>
</nav>
</div>
);
}
Maindata
export default function Maindata({ city = "mansehra" }) {
const [data, setData] = useState();
const weather = async (city) => {
const key = "XYZ";
await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}&units=metric&formatted=0`
)
.then((response) => response.json())
.then((actualData) => setData(actualData));
};
useEffect(() => {
if (city) {
weather(city); // <-- pass city through to function
}
}, [city]);
if (!data) {
return <div>Loading...</div>;
}
const link = `http://openweathermap.org/img/w/${data.weather[0].icon}.png`;
return (
<>
<div className="maindata">
<div className="city">{data.name}</div>
<div className="temp">{data.main.temp} C</div>
<div className="icon">
<img src={link} alt="not found" />{" "}
</div>
<div className="feel">feels Like {data.main.feels_like} C</div>
<div className="wind">Wind {data.wind.speed} Km/hr</div>
<div className="cloudy">{data.weather[0].main}</div>
<div className="humidity">humidity {data.main.humidity}%</div>
<div className="sunrise">
sunrise :- {new Date(data.sys.sunrise * 1000).toUTCString()}{" "}
</div>
<div className="sunset">
sunset :- {new Date(data.sys.sunset * 1000).toUTCString()}
</div>
</div>
</>
);
}