skip to Main Content

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.

2

Answers


  1. This should be inside a single function with async-await or Promise. Let’s see a code here:

    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";
    
    useEffect(() => {
      // use async on the function where we are using the `await` keyword
      const handleFetchDataAndSetImage = async () => {
        // let's wait for the data from API using await
        const { data } = await axios.get("/your/api/endpoint"); // or you can use fetch instead of axios
        // now we have data
        handleSetBg();
      };
    
      handleFetchDataAndSetImage();
    }, []);
    
    const handleSetBg = () => {
      switch (weatherData ? weatherData.currentConditions.icon : "sn") {
        case "rain":
          setBgTheme(rain);
          break;
        case "fog":
          setBgTheme(fog);
          break;
        case "cloudy":
          setBgTheme(cloudy);
          break;
        case "snow":
          setBgTheme(snow);
          break;
        case "wind":
          setBgTheme(wind);
          break;
        case "sn":
          setBgTheme(sn);
          break;
        default:
          setBgTheme(sn);
      }
    };
    
    Login or Signup to reply.
  2. 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} />    
      )
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search