render components conditionally after unsuccessful results

Viewed 40

my previous question led me here and after being able to access and use musixmatch API successfully, I now see that not all the songs have lyrics

so I'm getting the songs but they are some songs that don't have their lyrics published yet and I want to handle this error I first set the lyrics to setLyrics, then check if its undefined and use a spinner to load and then disappear when the fetch returns results

return trackInfo ===undefined||lyrics===undefined ||Object.keys(trackInfo).length===0 
       ||Object.keys(lyrics).length===0 ? 
       <Spinner/>:<Songlyrics/>

but what if the resource never comes because it doesn't exist, the spinner just keeps loading indefinitely, I want the spinner to load for a few seconds but if there are no lyrics for a particular song, render a component that tells the user that the resource isn't available and reroute to the home page

I have tried using a setTimeout but now even if the lyric is available I'm still rerouted which tells me I'm missing something, I also need to figure out a way to render the noLyrics message component

    return trackInfo ===undefined||lyrics===undefined ||Object.keys(trackInfo).length===0 ||Object.keys(lyrics).length===0 ? 
         <>
          <Spinner/>
          setTimeout(()=>{
            navigate('/')
},6000)
         </>
:<Songlyrics/>

can someone help me? for more context

function Lyrics() {
    const [lyrics,setLyrics]=useState('')
    const [loading,setLoading]=useState(false)

    const navigate =useNavigate()
    // get request for lyrics by id
    useEffect(()=>{
         setLoading(true)
      fetch('getting lyrics')
      .then(res=>res.json())
      .then(data=>{
            // setLyric to the lyric body
             setLoading(false)
            setLyrics(data.message.body.lyrics.lyrics_body)
        })
    
    },[])
      
     

  return loading ? <Spinner/>:
  (trackInfo ===undefined||lyrics===undefined ||Object.keys(trackInfo).length===0 ||Object.keys(lyrics).length===0?<DoesNotExist/>
  :
  (
    <component/>
  )
)

}
1 Answers

How do you determine from your state data whether the value is missing because it's still loading or whether the value is missing because it doesn't exist? That would be the condition to check.

If there's currently no way to infer that information, add a state value for it. For example, you could have something like:

const [isLoading, setIsLoading] = useState(true);

And in your markup:

{
  isLoading ? <Spinner/> :
  (/* the rest of your logic, conditionally determining if the value exists or not */)
}

Then you'd simply update isLoading when starting or completing any given API call for that operation. If there are multiple simultaneous calls, you'd need multiple values. (Maybe a state value for each, maybe an array of which calls are currently loading, that's really up to you.)

However you design it, overall the main point is that currently you have two states:

  1. Value exists
  2. Value doesn't exist

But you need three states:

  1. Value exists
  2. Value doesn't exist because it's still being fetched
  3. Value doesn't exist after completing the fetch
Related