Build a Quran Reader App with React
This post walks through building a working Quran reader in React. You will get a surah list, an ayah view with translations, and an audio player, all powered by the free UmmahAPI Quran API.
What we are building
By the end of this post you will have a React app with three parts: a sidebar that lists all 114 surahs, a main panel that shows the Arabic text and translation for the selected surah, and an audio player that plays each ayah using a chosen reciter. No API key is required to follow along, since UmmahAPI allows 5,000 requests every 15 minutes without one.
Project setup
Start a new React project with Vite. It's faster than Create React App and needs less config.
npm create vite@latest quran-reader -- --template react
cd quran-reader
npm install
npm run dev
You don't need any extra npm packages for API calls since we will use the built in fetch function. If you prefer, you can install axios with npm install axios, but this guide sticks to plain fetch.
Fetching the surah list
The first screen users see is a list of all surahs. Call the /api/quran/surahs endpoint and store the result in state with useState and useEffect.
import { useState, useEffect } from 'react';
function SurahList({ onSelect }) {
const [surahs, setSurahs] = useState([]);
useEffect(() => {
async function loadSurahs() {
const res = await fetch('https://ummahapi.com/api/quran/surahs');
const data = await res.json();
setSurahs(data.surahs);
}
loadSurahs();
}, []);
return (
<ul className="surah-list">
{surahs.map(surah => (
<li key={surah.number} onClick={() => onSelect(surah.number)}>
{surah.number}. {surah.englishName}
</li>
))}
</ul>
);
}
export default SurahList;
Each surah object includes the Arabic name, English name, number of ayahs, and revelation place. This is enough to build a clean list with no extra requests.
Tip. Check the shape of the response before writing your component. Open /api/quran/surahs in your browser first, so you know the exact field names.
Loading a full surah with ayahs
When a user clicks a surah, fetch the full surah with /api/quran/surah/:number. Add the translations query param to get English text alongside the Arabic.
function SurahView({ number }) {
const [surah, setSurah] = useState(null);
useEffect(() => {
if (!number) return;
async function loadSurah() {
const url = `https://ummahapi.com/api/quran/surah/${number}?translations=en&script=uthmani`;
const res = await fetch(url);
const data = await res.json();
setSurah(data);
}
loadSurah();
}, [number]);
if (!surah) return <p>Loading...</p>;
return (
<div className="surah-view">
<h2>{surah.englishName}</h2>
{surah.ayahs.map(ayah => (
<div key={ayah.number} className="ayah">
<p className="arabic">{ayah.text}</p>
<p className="translation">{ayah.translations.en}</p>
</div>
))}
</div>
);
}
The script query param controls how the Arabic text looks. Use uthmani for standard Mushaf style, indopak for the script common in South Asia, or tajweed if you want color coded tajweed rules. Full details are on the Quran API page.
Adding audio playback
To play recitation, request a reciter with the reciter query param. Each ayah in the response includes an audio file URL you can load directly into an HTML audio element.
function AyahAudio({ surahNumber, ayahNumber }) {
const [audioUrl, setAudioUrl] = useState('');
useEffect(() => {
async function loadAyah() {
const url = `https://ummahapi.com/api/quran/surah/${surahNumber}/ayah/${ayahNumber}?reciter=alafasy`;
const res = await fetch(url);
const data = await res.json();
setAudioUrl(data.audio);
}
loadAyah();
}, [surahNumber, ayahNumber]);
return audioUrl ? <audio controls src={audioUrl} /> : null;
}
You can swap alafasy for any of the other reciters: abdul_basit, sudais, husary, ajamy, shaatri, muaiqly, or dosari. Let users pick their favorite with a simple dropdown tied to state.
Combining components into an app
Now put the pieces together. The parent component tracks which surah is selected and renders the list and the view side by side.
function App() {
const [selectedSurah, setSelectedSurah] = useState(1);
return (
<div className="app">
<SurahList onSelect={setSelectedSurah} />
<SurahView number={selectedSurah} />
</div>
);
}
export default App;
This gives you a working reader. Clicking a surah in the list updates state, which triggers the useEffect in SurahView to fetch fresh data.
Adding search
Users often want to jump to a specific verse by keyword instead of browsing surah by surah. The search endpoint makes this easy.
async function searchAyahs(query) {
const res = await fetch(`https://ummahapi.com/api/quran/search?q=${query}`);
const data = await res.json();
return data.results;
}
Wire this to a search input with a debounce if you expect users to type quickly, so you don't fire a request on every keystroke.
Handling rate limits and errors
Without an API key you get 5,000 requests per 15 minutes, which is plenty for development and small apps. For production traffic, register for a free key at ummahapi.com/register to remove the limit. Always wrap fetch calls in a try/catch so a network error doesn't crash the UI.
async function safeFetch(url) {
try {
const res = await fetch(url);
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
return await res.json();
} catch (err) {
console.error(err);
return null;
}
}
Tip. If you want to show tafsir alongside the ayah, call /api/tafsir/ibn_kathir/surah/:s/ayah/:a in a separate request when a user clicks a verse. Check the Tafsir API page for available collections.
FAQ
Do I need an API key to build a Quran app with React?
No. UmmahAPI allows 5,000 requests per 15 minutes without a key. If you want unlimited requests, register for a free key at ummahapi.com/register.
How do I get audio recitation for a surah in React?
Pass a reciter query param like ?reciter=alafasy to the surah endpoint. Each ayah object returned includes an audio URL you can load into an HTML audio element.
Can I show multiple translations at once?
Yes. Use the translations query param with comma separated language codes, for example ?translations=en,ur,fr, and the response will include each translation alongside the Arabic text.
What React hooks do I need for a Quran reader?
You mainly need useState to hold surah and ayah data and useEffect to fetch data when the component mounts or when the selected surah changes.
Ready to build?
UmmahAPI gives you free access to the full Quran text, translations, and audio recitations for your app.
Read the docs