Home > front end >  Function inside ternary causing infinite loop
Function inside ternary causing infinite loop

Time:04-29

Not sure why but a function inside my ternary is causing an infinite loop. The setUnit function, which is setting a state in redux, causes the page to loop infinitely/ breaks the page and I cannot put my figure on why. The function modifies the ternary that the component is dependent on, so maybe that's why?

Current.js

const Current = () => {
  const locationData = useSelector((state) => state.locationData);
  const locationName = useSelector((state) => state.locationName.name);
  const weatherData = useSelector((state) => state.weather.data);
  const unit = useSelector((state) => state.units.unit);
  const dispatch = useDispatch();

 
  function setUnit(unit) {
    if (unit === "metric") {
      console.log("metric!");
      dispatch(unitActions.setToMetric());
    } else {
      console.log("imperial!");
      dispatch(unitActions.setToImperial());
    }
  }

  
  return (
    <div className="main-container">
      <h2 className="location">{locationName}</h2>
      <div className="top">
        <img
          src={`https://openweathermap.org/img/wn/${weatherData.current.weather[0].icon}@2x.png`}
          alt="Weather icon"
          className="weather-icon"
        />
        <h1 className="temp">{Math.floor(weatherData.current.temp)}°</h1>
        <div className="units-container">
          {unit === "metric" ? (
            <div>
              <div className="unit" id="C">
                <h2>C</h2>
              </div>

              <div
                className="unit"
                id="F"
                onClick={setUnit("imperial")}
              >
                <h2>F</h2>
              </div>

              <div className="background"></div>
            </div>
          ) : (
            <div>
              <div className="unit" id="F">
                <h2>F</h2>
              </div>

              <div
                className="unit"
                id="C"
                onClick={setUnit("metric")}
              >
                <h2>C</h2>
              </div>

              <div className="background"></div>
            </div>
          )}
        </div>
      </div>
      <div className="bottom">
        <h2 className="description">
          {weatherData.current.weather[0].description[0].toUpperCase()}
          {weatherData.current.weather[0].description.substring(1)}
        </h2>
        <h4 className="timestamp">
          Updated as of {convertTime(weatherData.current.dt, "HH-MM")}
        </h4>
        <div className="bottom-icons">
          <div className="icons" id="top-icons">
            <div className="icon-element">
              Feels like {weatherData.current.feels_like}°
            </div>
            <div className="icon-element" id="wind">
              Wind {weatherData.current.wind_speed}km
            </div>
            <div className="icon-element" id="visibility">
              Visibility {Math.round(weatherData.current.visibility / 1000)} km
            </div>
          </div>
          <div className="icons">
            <div className="icon-element">
              Barometer {weatherData.current.pressure} mb
            </div>
            <div className="icon-element" id="humidity">
              Humidity {weatherData.current.humidity}%;
            </div>
            <div className="icon-element" id="dew">
              Dew Point {Math.round(weatherData.current.dew_point)}°
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

CodePudding user response:

Currently setUnit is being called immediately, changing state and causing it to continuously re-render. Instead, pass in your setUnit function to onClick to call it only when the onClick event is fired: onClick={() => setUnit("imperial")}.

CodePudding user response:

Another option is to change setUnit to return an event handler. An advantage of this approach is the event is colocated with the effect -

const setUnit = (unit) => (event) => {
  // access to `event` here            
  • Related