Labs ICT
Pro Login

Loading States

Showing loading indicators while data loads.

Loading States

Ever visited a website that just sat there blank while loading? Frustrating right? Loading states tell users something is happening. They turn an awkward silence into a conversation.

Good loading states reduce perceived wait time and keep users from rage-clicking the refresh button. Trust me, your users will thank you.

Simple Loading Indicator

The quickest approach is showing a text or spinner while data loads. It is simple but effective for most cases.

import { useState, useEffect } from 'react'

function DataLoader() {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(res => res.json())
      .then(result => {
        setData(result)
        setLoading(false)
      })
  }, [])

  if (loading) return 
Loading...
return
{JSON.stringify(data)}
}

The loading state starts as true and flips to false once data arrives. Simple as flipping a light switch.

Skeleton Screens

Skeleton screens show placeholder shapes that mimic your content layout. They feel more polished than a plain spinner because users can see the layout taking shape.

function UserCard({ loading, user }) {
  if (loading) {
    return (
      
) } return (
{user.name}

{user.name}

{user.bio}

) }

The placeholder divs have the same dimensions as real content. When data loads, you swap the skeleton for actual content. It feels smooth and professional.

Progress Indicators

For longer operations like file uploads, a progress bar gives users a clear picture of how much time is left. It turns uncertainty into a countdown.

import { useState } from 'react'

function FileUpload() {
  const [progress, setProgress] = useState(0)
  const [uploading, setUploading] = useState(false)

  const handleUpload = async (file) => {
    setUploading(true)
    const formData = new FormData()
    formData.append('file', file)

    const xhr = new XMLHttpRequest()
    xhr.upload.onprogress = (e) => {
      if (e.lengthComputable) {
        setProgress(Math.round((e.loaded / e.total) * 100))
      }
    }
    xhr.onload = () => setUploading(false)
    xhr.open('POST', '/api/upload')
    xhr.send(formData)
  }

  if (uploading) {
    return (
      

{progress}% uploaded

) } return }

The XMLHttpRequest API gives us upload progress events. Combine this with a styled bar and users always know where they stand.

Try it Yourself →