0

I have a form with next fields:

  1. A drop-down list that allows to choose a branch + A city that is automatically selected according to the branch selected.
  2. A calendar component that allows to select a date + A details about the date that automatically displays, such as whether it is a work day or a holiday.
  3. Filleds with the temperature details that automatically displays, depending on the city of the branch and date selected. It updated whenever either of them changes, and both are validted.

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> &emsp; <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 } /> &emsp; <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 } /> &emsp; <h3>{Languages.temperature[selectedLanguage]}:</h3>{" "} <input readOnly disabled="disabled" value={weather} /> {" \u2103"} </fieldset> </form> </> ); } 

A screenshot of the problem

4
  • 1
    Please add some code so we can help diagnose and explain the issue. It is likely that you have a dependency in the useEffect dependency array that is either changing a lot, or is "complex" in some way (e.g it is a (JSON) Object). Commented Dec 19, 2022 at 9:33
  • show some code please Commented Dec 19, 2022 at 9:36
  • Your second useEffect doesn't have a dependency array Commented Dec 19, 2022 at 11:55
  • Thanks Harrison and Raziel, I added the code. Thanks Konrad. When I add empty dependency array, it completely cancels the call to the API temperature. Commented Dec 19, 2022 at 12:21

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

When I add empty dependency array, it completely cancels the call to the API temperature.
When it was mentioned "If you pass some values, it'll run again when one of those values is changed", that's what you need to do. I also updated the answer with some ideas and the React Hooks Docs.
Thanks @Ilê Caian, you solved my problem. branch should also be added: [branch, cities, selectedBranchIndex, selectedDate]

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.