Search code examples
reactjsfetchrender

React condition render before the call


The condition is calling before fetch, so I can't render the image on the page.

I need to set an icon based on the API data.

  1. Call an API for weather data, then set it to weatherData state

  2. Set the weather Icon/image based on the data

Here Icon/image is external, so I use a switch statement to define the icon

import rain from "../src/Images/rain.jpg";
import fog from "../src/Images/fog.jpg";
import snow from "../src/Images/snow.jpg";
import wind from "../src/Images/wind.jpg";
import cloudy from "../src/Images/cloudy.png";
import sn from "../src/Images/sn.jpg";

let newBG;


 useEffect(() => {
    fetchData             // <==fetching data 
  }, []);


  useEffect(() => {
    setbgTheme(newBg);    // <== setting Bg
  }, [newBG]);



switch (weatherData? weatherData.currentConditions.icon: "sn") {
      case "rain":
        newBg = rain;
        break;
      case "fog":
        newBg = fog;
        break;
      case "cloudy":
        newBg = cloudy;
        break;
      case "snow":
        newBg = snow;
        break;
      case "wind":
        newBg = wind;
        break;
      case "sn":
        newBg = sn;
        
    }

Here switch statement is called before the fetch, so I use a setTimeout function for the switch statement.

Still, it is not rendering.


Solution

  • I think using {} as dict will increase readability of your code, compare to switch-case statement. Also it is better to use component state to keep response value you get from the api, and derive icon from it. You don't need setTimeout or anything.

    Here is how you can achieve this:

    import rain from "../src/Images/rain.jpg";
    import fog from "../src/Images/fog.jpg";
    import snow from "../src/Images/snow.jpg";
    import wind from "../src/Images/wind.jpg";
    import cloudy from "../src/Images/cloudy.png";
    import sn from "../src/Images/sn.jpg";
    
    // known weather images dict
    const weatherImgs = {
     rain,
     fog,
     snow,
     wind,
     cloudy,
     sn
    };
    
    function getWeatherImage(data, defaultImage = 'sn') {
      // try to resolve image or fallback to default
      const image = weatherImgs[data?.currentConditions?.icon ?? defaultImage];
      // extra check in case there is value from api  we don't have image for.
      return image ?? weatherImgs[defaultImage];
    }
    
    function YourComponent() {
      // storing api response, not image,
      const [data, setData] = useState(null);  
    
      useEffect(() => {
        async function fetchData() {
          const response = await fetch("your.app/api/method");
          cons json = await response.json();
          setData(json);
        }
        fetchData();
      }, []);
    
      // resolving image icon 
      const weatherImage = getWeatherImage(data);
    
      return (
        <img src={weatherImage} />    
      )
    }