I'm trying to set the background of my React App to the NASA APOD (Astronomy Picture of the Day). Here is my code for that:
import './App.css';
import React, { useState, useEffect } from "react";
const apiKey = process.env.REACT_APP_NASA_KEY;
function App() {
const [bg, setBg] = useState(null);
async function fetchPhoto() {
const dat = await fetch(`https://api.nasa.gov/planetary/apod?api_key=${apiKey}`);
const data = await dat.json();
setBg(data);
}
useEffect(() => {
fetchPhoto().then(() => {
document.body.style.backgroundImage = `url('${bg.url}')`
})
}, [])
return null;
}
However, in this code then
does not wait for the state to be set and I get the error:
App.js:22 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'url')at App.js:22:1
What am I doing wrong? Thanks!
CodePudding user response:
1. Solution
A simpler way to achieve what you want is by doing like below, this way you don't have to menage asynchronous tasks like you are doing:
import './App.css';
import React, { useState, useEffect } from "react";
const apiKey = process.env.REACT_APP_NASA_KEY;
function App() {
const [bg, setBg] = useState(null);
async function fetchPhoto() {
const dat = await fetch(`https://api.nasa.gov/planetary/apod?api_key=${apiKey}`);
const data = await dat.json();
setBg(data);
}
useEffect(() => {
fetchPhoto()
}, [])
useEffect(() => {
if(bg){
document.body.style.backgroundImage = `url('${bg.url}')`;
}
}, [bg])
return null;
}
2. Explanation
Your code is not working because just after fetchPhoto()
is executed and resolved, React did not yet re-render the components (update the state), therefore bg
is still null
.
CodePudding user response:
Do you need the state for something else? If not, you could avoid it:
function App() {
useEffect(() => {
const fetchPhoto = async () => {
const dat = await fetch(`https://api.nasa.gov/planetary/apod?api_key=${apiKey}`);
const data = await dat.json();
if (data) {
document.body.style.backgroundImage = `url('${data.url}')`;
}
}
fetchPhoto();
}, [])
return null;
}