Home > Back-end >  Stop Re-render on onChange input Reactjs
Stop Re-render on onChange input Reactjs

Time:11-04

console.log(result); In code here is being logged in the console every time there is an onChange in the input. looking for a way to stop component re-render on input value change.

import "./home.css";

const Home = () => {
  const [city, setCity] = useState("kampala");
  const [result, setResult] = useState(null);

  const fetchApi = async (city) => {
    const data = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=`api
key_here``
    ).then((res) => res.json())
    .then((data) => setResult(data));

   
  };

  useEffect(() => {
    fetchApi(city);
    console.log("heyy");
  }, []);

  const handleSubmit = async (e) => {
    e.preventDefault();
    await fetchApi(city);
  };

  if(result === null) {
    return <p>Loading</p>
  }

  console.log(result);//this is logged in the console on every character change in the input. need to stop the re-render

  return (
    <div className="home__container">
      <div className="home__img">
        <div className="home__hero__info">
          <div>
            <h1>26 C</h1>
          </div>
          <div>
            <h3>Kampala</h3>
            <p>31 - October - 2022</p>
          </div>
          <div>
            <p>Suuny</p>
          </div>
        </div>
      </div>
      <div className="home__details">
        <div className="weather__div">
          <form onSubmit={handleSubmit}>
            <input
              type="text"
              className="home__input"
             
              onChange={(e) => setCity(e.target.value)}
      
            />
            <button type="submit" className="weather__button">
              Search
            </button>
          </form>
          <div className="weather__ul">
            <ul>
              <li>Kampala</li>
              <li>Nairobi</li>
              <li>Dodoma</li>
            </ul>
          </div>
          <hr />
        </div>
        <div className="weather__div">
          <h4 className="h4">Weather Conditions</h4>
          <div>
            <span className="weather__details">
              <h4>Cloudy</h4>
              <h3>{result.clouds.all}%</h3>
            </span>
            <span className="weather__details">
              <h4>Humidity</h4>
              {/* <h3>{result.main.humidity}%</h3> */}
            </span>
            <span className="weather__details">
              <h4>Wind</h4>
              {/* <h3>{wind.speed}</h3> */}
            </span>
            <span className="weather__details">
              <h4>Rain</h4>
              <h3>23%</h3>
            </span>
          </div>
          <hr />
        </div>
      </div>
    </div>
  );
};

export default Home;

CodePudding user response:

Updating state will always cause a re-render, if you don't want a re-render to happen when updating your input than you want to use a React ref to manage the input value

const city = useRef("kampala");

Than in your input:

<input
 type="text"
 className="home__input"
 value={city.current}       
 onChange={(e) => city.current = e.target.value}
 />

CodePudding user response:

Short answer: use a ref instead of a state:

const initialValue = "kampala";

const Home = () => {
  const city = useRef();
  const [result, setResult] = useState(null);

  ...

  useEffect(() => {
    fetchApi(initialValue);
    console.log("heyy");
  }, []);

  const handleSubmit = async (e) => {
    e.preventDefault();
    await fetchApi(city.current.value);
  };

  ...

  return (
    <div className="home__container">
      ...
          <form onSubmit={handleSubmit}>
            <input
              type="text"
              ref={city}
              className="home__input"
              value={initialValue}      
            />
            <button type="submit" className="weather__button">
              Search
            </button>
          </form>
      ...
    </div>
  );
};

Not so long answer:

You're storing city through a state: the purpose of a state is to trigger a rerender each time it's modified. So when you're updating city on input change, that's triggering the render.

References are a different mechanism in react: They are meant to store value across different rendering, but react is not looking at them to rerender on each update. The "react way" is to associate the ref with your input: when you're using city.current, you will get the HTML element of the current rendering. Then you can ask for its value, and voilà :)

  • Related