Reputation: 317
I have a form with next fields:
The check if the first two fields are validted, getting the temperature from API, and update the temperature fields in temperature (using useState), are done in useEffect. The problem is that every time there is a change in the first two fields, the API call is made two or three times.
I deleted the <React.StrictMode> and it doesn't help.
import Calendar from "../components/Calendar";
import Languages from "../components/Languages/Languages.json";
import React, { useContext, useEffect, useRef, useState } from "react";
import { ContextCities } from "../Contexts/ContextCities";
import { ContextLanguages } from "../Contexts/ContextLanguages";
import { loadBranches } from "../utils/branchesHandelApi";
import { loadWeather } from "../utils/weatherHandelApi";
export default function Transactions() {
const { cities } = useContext(ContextCities);
const { selectedLanguage } = useContext(ContextLanguages);
const [branch, setBranch] = useState([]);
const [selectedBranchIndex, setSelectedBranchIndex] = useState(0);
const [selectedDate, setSelectedDate] = useState();
const [selectedDateData, setSelectedDateData] = useState();
const [weather, setWeather] = useState(0);
const handleSubmitTransaction = async (e) => {
e.preventDefault();
// saveTransactions(transaction);
};
useEffect(() => {
loadBranches(setBranch);
}, []);
const isInitialMount = useRef(true);
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
if (
cities !== "undefined" &&
selectedBranchIndex !== 0 &&
selectedDate
) {
let station_id = cities.cities.find(
(itm) => itm.Name === branch[selectedBranchIndex - 1].city
).meteorological_station.id;
console.log("station_id", station_id);
loadWeather(station_id, selectedDate, setWeather);
} else setWeather(0);
}
});
return (
<>
<h1>
<span style={{ fontSize: "2rem", fontFamily: "Noto Color Emoji" }}>
{"\ud83d\udcb3"}
</span>{" "}
{Languages.transactions[selectedLanguage]}
</h1>
<form
autoComplete="off"
className="App"
id="form"
onSubmit={(e) => handleSubmitTransaction(e)}
>
<fieldset>
<legend>
<h2>{Languages.manual_update[selectedLanguage]}</h2>
</legend>
<h2>{Languages.branches[selectedLanguage]}</h2>
<h3>{Languages.name[selectedLanguage]}:</h3>{" "}
<select
defaultValue=""
name="branch"
required
onChange={(e) => setSelectedBranchIndex(e.target.selectedIndex)}
>
<option hidden value="">
{Languages.name[selectedLanguage]}
</option>
{branch.map((itm, index) => (
<option key={index}>{itm.name}</option>
))}
</select>
 
<h3>{Languages.city[selectedLanguage]}:</h3>{" "}
<input
disabled="disabled"
readOnly
value={
selectedBranchIndex === 0
? ""
: branch[selectedBranchIndex - 1].city
}
/>
<br />
<br />
<h2>{Languages.date[selectedLanguage]}</h2>
<Calendar
setSelectedDate={setSelectedDate}
setSelectedDateData={setSelectedDateData}
/>
<br />
<br />
<h2>{Languages.weather[selectedLanguage]}</h2>
<h3>{Languages.meteorological_station_id[selectedLanguage]}:</h3>{" "}
<input
readOnly
disabled="disabled"
value={
selectedBranchIndex === 0 || cities === "undefined"
? ""
: cities.cities.find(
(itm) =>
itm.Name === branch[selectedBranchIndex - 1].city
).meteorological_station.id
}
/>
 
<h3>
{Languages.meteorological_station_location[selectedLanguage]}:
</h3>{" "}
<input
readOnly
disabled="disabled"
value={
selectedBranchIndex === 0 || cities === "undefined"
? ""
: cities.cities.find(
(itm) =>
itm.Name === branch[selectedBranchIndex - 1].city
).meteorological_station.name
}
/>
 
<h3>{Languages.temperature[selectedLanguage]}:</h3>{" "}
<input readOnly disabled="disabled" value={weather} />
{" \u2103"}
</fieldset>
</form>
</>
);
}
Upvotes: 0
Views: 176
Reputation: 655
You need to add the dependency array to your second useEffect()
, otherwise it'll keep executing indefinitely every time the component re-renders. If you define it empty, it'll run once at the first render. If you pass some values, it'll run again when one of those values is changed. Here is an example with an empty array of dependencies a dependency array with some variables that are used inside the hook:
useEffect(() => {
if (
cities !== "undefined" &&
selectedBranchIndex !== 0 &&
selectedDate
) {
let station_id = cities.cities.find(
(itm) => itm.Name === branch[selectedBranchIndex - 1].city
).meteorological_station.id;
console.log("station_id", station_id);
loadWeather(station_id, selectedDate, setWeather);
} else {
setWeather(0);
}
}, [cities, selectedBranchIndex, selectedDate]);
As you asked in the comments section (and it was mentioned there) you need to pass the variables you want to "listen" for changes. From the code you posted, I suppose they are cities
, selectedBranchIndex
, selectedDate
, so you just need to add them there. Trim that based on your code/needs. You could read more about the useEffect()
hook, its dependency array, and how it works at the Official React Docs
Upvotes: 1