Home > database >  Building a Weather App with React and I am running into a problem where I need to click a button twi
Building a Weather App with React and I am running into a problem where I need to click a button twi

Time:10-07

The title was rather vague so I will try to explain in a bit more detail here. I have a button that swaps between imperial and metric units. It changes the params in the API URL and re-renders the component that displays the weather. Now my button to swap from Day Weather to Night Weather works instantly when clicked but I am running into a weird problem where my button that swaps from metric to imperial needs to be double clicked when swapping from imperial to metric. Here's a link to the project if you want to reproduce the bug. Thank you for all the help.

http://react-weather-app-trevinshu.vercel.app/

Code for state calls:

 let toggle = false;

  const [displayedWeather, setDisplayedWeather] = useState(null);
  const [loading, setLoading] = useState(false);
  const [swapUnit, setUnits] = useState(`https://dataservice.accuweather.com/forecasts/v1/daily/5day/${key}?apikey=${apiKey}&details=true&metric=true`);
  const [buttonText, setButtonText] = useState('metric');

Here's my code for the API call:

  useEffect(() => {
    setLoading(true);

    //Fetch selected weather forecast
    const displayWeather = async () => {
      const data = await fetch(swapUnit);
      const result = await data.json();
      setDisplayedWeather(result);
    };

    //Timeout to delay display of weather forecast & show loading state
    setTimeout(() => {
      displayWeather();
      toast.success(`Weather for ${city}`, { position: 'top-center', hideProgressBar: true, toastId: customId });
      setLoading(false);
    }, 2000);
  }, [swapUnit]);

Here's my code for the button function to toggle from metric to imperial and vice versa:

 //Toggle between celsius and fahrenheit
  function changeParams(e) {
    e.preventDefault();
    toggle = !toggle;

    if (toggle) {
      setButtonText('Metric');
      setUnits(`https://dataservice.accuweather.com/forecasts/v1/daily/5day/${key}?apikey=${apiKey}&details=true&metric=false`);
    } else {
      setButtonText('Imperial');
      setUnits(`https://dataservice.accuweather.com/forecasts/v1/daily/5day/${key}?apikey=${apiKey}&details=true&metric=true`);
    }
  }

CodePudding user response:

each time any of your states change you redefine toggle to false thats how component rendering works to fix the issue you could do something like this:

function changeParams(e) {
    e.preventDefault();

    if (buttonText === 'Imperial') {
      setButtonText('Metric');
      setUnits(`https://dataservice.accuweather.com/forecasts/v1/daily/5day/${key}?apikey=${apiKey}&details=true&metric=false`);
    } else {
      setButtonText('Imperial');
      setUnits(`https://dataservice.accuweather.com/forecasts/v1/daily/5day/${key}?apikey=${apiKey}&details=true&metric=true`);
    }
  }
  • Related