Skip to content

Code Patterns

leanwrldd edited this page Aug 17, 2026 · 1 revision

← Back to Home

Code Patterns

Fetch Utility

Always use a utility function — never fetch inline in components.

// lib/juicewrld.ts
const BASE = 'https://juicewrldapi.com/juicewrld'

export async function apiFetch(
  path: string,
  params: Record<string, string | number | undefined> = {},
  opts: { method?: string; token?: string; body?: unknown } = {}
) {
  const url = new URL(BASE + path)
  Object.entries(params).forEach(([k, v]) => {
    if (v != null) url.searchParams.set(k, String(v))
  })
  const headers: Record<string, string> = {}
  if (opts.token) headers['Authorization'] = `Token ${opts.token}`
  if (opts.body)  headers['Content-Type'] = 'application/json'
  const res = await fetch(url, {
    method: opts.method ?? 'GET',
    headers,
    body: opts.body ? JSON.stringify(opts.body) : undefined,
  })
  if (!res.ok) throw new Error(`API error ${res.status}`)
  return res.json()
}

React Hook Pattern

// hooks/useSongs.ts
import { useState, useEffect } from 'react'
import { apiFetch } from '../lib/juicewrld'

export function useSongs({
  category, era, search, searchall, lyrics,
  page = 1, page_size = 20
} = {}) {
  const [data, setData]       = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError]     = useState(null)

  useEffect(() => {
    setLoading(true)
    apiFetch('/songs/', { category, era, search, searchall, lyrics, page, page_size })
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false))
  }, [category, era, search, searchall, lyrics, page, page_size])

  return { songs: data?.results ?? [], count: data?.count ?? 0, loading, error }
}

Audio Streaming

// Simple — browser handles range/seeking automatically
<audio
  controls
  src={`https://juicewrldapi.com/juicewrld/files/download/?path=${encodeURIComponent(song.path)}`}
/>

// Tier check before rendering play button
{song.path && (
  <button onClick={() => playSong(song)}>▶</button>
)}

Tips

  • Use song.path directly as the stream path — it's already in the right format.
  • The browser <audio> element handles Range requests automatically — just set src.
  • Debounce search inputs 300–500 ms to avoid hammering the API.
  • track_titles is an array — a song may have multiple alternative titles. Show the first or let users pick.
  • Not all songs have a path (some are metadata-only). Check before rendering a play button.
  • image_url is relative — prepend https://juicewrldapi.com.
  • Use /radio/random/ for a shuffle/discover feature — it already returns a playable file.
  • Check /account/me/ first to know the role — don't probe restricted endpoints and handle 403s.

Clone this wiki locally