Background Image not displaying Inline React

Viewed 54

The goal is to display different backgrounds depending on the fetched weather data. I'm trying to set the background inline in the JSX. On the first fetch, the data is populated but the background doesn't change until I click the search icon again. I've tried bundling both the fetch function and background handler function in one function then setting that function onClick and I've tried adding the backgroundHandler at the end of the fetch function. Both require an additional click after the initial fetch. On each occasion, you can see a 404 error on the initial fetch to populate the data. The photo I'm testing is imported into React as (cloudy).

Both Functions bundled into RenderUI Function

const WeatherContainer = () => {
    const [searchTerm, setsearchTerm] = useState()
    const [currentWeather, setCurrentWeather] = useState({});
    const [forecastedWeather, setForecastedWeather] = useState({});
    const [loading, setLoading] = useState(false);
    const [background, setBackground] = useState()
    
    const handleInput = (e) => {
        setsearchTerm(e.target.value);
    }

    // Dynamically changes background depending on current weather
    const backgroundHandler = () => {
        // Day Backgrounds
        if (Object.keys(currentWeather).length > 0) {
             if (currentWeather.weather[0].icon === '02d' || currentWeather.weather[0].icon === '04d' ) {
                setBackground(cloudy)
            }
        }
    };
    
    const handleSearch = () => {
        fetch(`/weather/${searchTerm}`)
            .then(res => { return res.json() })
            .then(result => {
                setCurrentWeather({ ...result.data })
            })
    };

    const renderUI = () => {
        handleSearch();
        backgroundHandler();
    }


    return (
        <div>
            <div className='search-bar'>
                    <input className='text_input' type='text' name='searchTerm' onChange={handleInput} placeholder='Enter city' />
                    <button className='search-button' onClick={renderUI} type='submit' value='submit' name='button'>
                        <Icon icon={searchIcon} flip="horizontal" />
                    </button>
            </div>
            
            <div className='weather-container' style={{ backgroundImage: `url(${background})` }}>
                {Object.keys(currentWeather).length > 0
                    ? <>
                        <CurrentWeatherComponent
                            currentWeather={currentWeather}/>
                        <ForecastContainer />
                      </>
                    : <></>
                }
            </div>  
        </div>
    )

};

enter image description here

BackgroundHandler called at the end of handleSearch Function

const WeatherContainer = () => {
    const [searchTerm, setsearchTerm] = useState()
    const [currentWeather, setCurrentWeather] = useState({});
    const [forecastedWeather, setForecastedWeather] = useState({});
    const [loading, setLoading] = useState(false);
    const [background, setBackground] = useState()
    
    const handleInput = (e) => {
        setsearchTerm(e.target.value);
    }

    // Dynamically changes background depending on current weather
    const backgroundHandler = () => {
        // Day Backgrounds
        if (Object.keys(currentWeather).length > 0) {
             if (currentWeather.weather[0].icon === '02d' || currentWeather.weather[0].icon === '04d' ) {
                setBackground(cloudy)
            }
        }
    };
    
    const handleSearch = () => {
        fetch(`/weather/${searchTerm}`)
            .then(res => { return res.json() })
            .then(result => {
                setCurrentWeather({ ...result.data })
            })
        backgroundHandler();
    };

    return (
        <div>
            <div className='search-bar'>
                    <input className='text_input' type='text' name='searchTerm' onChange={handleInput} placeholder='Enter city' />
                    <button className='search-button' onClick={handleSearch} type='submit' value='submit' name='button'>
                        <Icon icon={searchIcon} flip="horizontal" />
                    </button>
            </div>
            
            <div className='weather-container' style={{ backgroundImage: `url(${background})` }}>
                {Object.keys(currentWeather).length > 0
                    ? <>
                        <CurrentWeatherComponent
                            currentWeather={currentWeather}/>
                        <ForecastContainer />
                      </>
                    : <></>
                }
            </div>  
        </div>
    )

};

enter image description here

2 Answers

Change backgroundHandler to a useEffect with currentWeather as a dependency (just copy the function body and put inside it). useState is async and may not be set yet when you run backgroundWeather, that's why its blank

use ternary operator

background ? background : '#your default image

Related