I want to fetch new data using the new parameter being passed to the useFetch
hook which has a default fetch when the app mounts for the first time. The second fetch and more fetches are supposed to happen when the user fills in the input to enter a new city and submits, then that city’s data is brought back.
useFetch Hook
import { useQuery } from "@tanstack/react-query";
const useFetch = function (city:string='kampala') {
const { isLoading, error, data } = useQuery({
queryKey: ["weatherData"],
queryFn: () =>
fetch(
`http://api.weatherapi.com/v1/forecast.json?key=516e576e876042b9b7665337232403&q=${city}&days=7`
).then((res) => res.json()),
});
return { isLoading, error, data };
};
export default useFetch;
The search component below
import React, { useState } from "react";
import { BsSearch } from "react-icons/bs";
import useFetch from "../../../hooks/useFetch";
import "./header.css";
type Props = {};
function Header({}: Props) {
// const [city, setCity] = useState("kampala");
const city = React.useRef<HTMLInputElement>(null);
const handleSubmit = async (e: any) => {
e.preventDefault();
useFetch(city.current?.value);
// city.current.value = "";
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
return (
<div className="lovez">
<div className="lovek">
<h1 style={{ color: "#F5AF26" }}>Weather Forcast</h1>
<p>{new Date("2023-03-24").toDateString()}</p>
</div>
<div className="header__search">
<form onSubmit={handleSubmit}>
<input
type="text"
className="home__input"
ref={city}
name="city"
placeholder="Choose City"
/>
<button type="submit" className="weather__button">
Search
</button>
</form>
</div>
</div>
);
}
export default Header;
2
Answers
First, you should save
city
in state instead of ref, so that when you change it, the component is re-rendered.Second, you should pass
city
to thequeryKey
paramater, react-query will automatically resend the request when the city changes. You can read more about this here.It should look something like the following:
First of all, you are violating rules of hooks by calling
useFetch
inside a "standard JavaScript" functionhandleSubmit
that is neither a React function component nor a custom React Hook function. YouuseFetch
becomes a hook as you have written another hook inside ituseQuery
.I would suggest you to rename
useFetch
to something more relatable likeuseCityWeather
.For the actual solution, you can do following as suggested by @Enve: use a local state to store the city data and whenever it’s updated, all the hooks inside the component including
useFetch
will be called again with the updated state.In case you want to initialize the state with a data passed by
props
, you can write like this: