Skip to main content
Utility hooks and functions provide common functionality for debouncing, HTML parsing, date calculations, and more.

Hooks

useDebounce

Debounces a value, delaying updates until after a specified delay has passed since the last change. Useful for optimizing search inputs and other rapidly changing values.
value
T
required
The value to debounce (can be any type)
delay
number
required
Delay in milliseconds before updating the debounced value

Returns

debouncedValue
T
The debounced value, updated only after the delay period

Usage

import { useDebounce, useVersions } from '@youversion/platform-react-hooks';
import { useState } from 'react';

function VersionSearch() {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearch = useDebounce(searchTerm, 300);
  
  // Only fetches when user stops typing for 300ms
  const { versions, loading } = useVersions('en', undefined, {
    enabled: debouncedSearch.length > 0,
  });
  
  const filteredVersions = versions?.data.filter(v => 
    v.title.toLowerCase().includes(debouncedSearch.toLowerCase())
  );
  
  return (
    <div>
      <input 
        type="text"
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
        placeholder="Search versions..."
      />
      {loading && <div>Searching...</div>}
      <ul>
        {filteredVersions?.map(v => (
          <li key={v.id}>{v.title}</li>
        ))}
      </ul>
    </div>
  );
}

useFilteredVersions

Filters a list of Bible versions based on search term, language, and recently used versions.
versions
BibleVersion[]
required
Array of Bible versions to filter
searchTerm
string
required
Search query to filter by title, abbreviation, or language
selectedLanguage
string
required
Language code to filter by (use ’*’ for all languages)
recentVersions
Pick<BibleVersion, 'id' | 'title' | 'localized_abbreviation'>[]
Optional array of recent versions to exclude from results

Returns

filteredVersions
BibleVersion[]
Filtered and sorted array of Bible versions

Usage

import { useFilteredVersions, useVersions } from '@youversion/platform-react-hooks';
import { useState } from 'react';

function VersionPicker() {
  const { versions } = useVersions('*');
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedLanguage, setSelectedLanguage] = useState('*');
  
  const filteredVersions = useFilteredVersions(
    versions?.data || [],
    searchTerm,
    selectedLanguage
  );
  
  return (
    <div>
      <input 
        type="text"
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
        placeholder="Search..."
      />
      <select 
        value={selectedLanguage}
        onChange={(e) => setSelectedLanguage(e.target.value)}
      >
        <option value="*">All Languages</option>
        <option value="en">English</option>
        <option value="es">Spanish</option>
      </select>
      
      <ul>
        {filteredVersions.map(v => (
          <li key={v.id}>{v.title} ({v.abbreviation})</li>
        ))}
      </ul>
    </div>
  );
}

useInitData

Combines version, book, and chapter data into a single hook for initialization. Useful when you need all three pieces of data loaded together.
version
number
default:"3034"
Bible version ID
book
string
default:"GEN"
USFM book abbreviation
chapter
number
default:"1"
Chapter number

Returns

loading
boolean
True if any of version, book, or chapter data is loading
error
string | null
Combined error messages from version, book, and chapter requests
data
InitData | null
Object containing version, book, and chapter data when all are loaded

Usage

import { useInitData } from '@youversion/platform-react-hooks';

function BibleReaderInit() {
  const { data, loading, error } = useInitData({
    version: 3034,
    book: 'JHN',
    chapter: 3,
  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!data) return null;

  return (
    <div>
      <h1>{data.version.title}</h1>
      <h2>{data.book.name} {data.chapter.number}</h2>
      <div dangerouslySetInnerHTML={{ __html: data.chapter.content }} />
    </div>
  );
}

useChapterNavigation

Provides navigation functionality for moving between chapters, including support for book boundaries and intro chapters.
Requires ReaderProvider to be present in the component tree.

Returns

canNavigatePrevious
boolean
Whether navigation to previous chapter is possible
canNavigateNext
boolean
Whether navigation to next chapter is possible
navigateToPrevious
() => void
Navigate to the previous chapter (may cross book boundaries)
navigateToNext
() => void
Navigate to the next chapter (may cross book boundaries)
currentChapterIndex
number
Index of current chapter within the current book
isLoading
boolean
Whether book data is being loaded

Usage

import { useChapterNavigation, ReaderProvider } from '@youversion/platform-react-hooks';

function ChapterNavigator() {
  const {
    canNavigatePrevious,
    canNavigateNext,
    navigateToPrevious,
    navigateToNext,
    currentChapterIndex,
    isLoading,
  } = useChapterNavigation();
  
  return (
    <div>
      <button 
        onClick={navigateToPrevious}
        disabled={!canNavigatePrevious || isLoading}
      >
        Previous Chapter
      </button>
      
      <span>Chapter {currentChapterIndex + 1}</span>
      
      <button 
        onClick={navigateToNext}
        disabled={!canNavigateNext || isLoading}
      >
        Next Chapter
      </button>
    </div>
  );
}

// Must be wrapped in ReaderProvider
function App() {
  return (
    <ReaderProvider currentVersion={v} currentBook={b} currentChapter={c} currentVerse={null}>
      <ChapterNavigator />
    </ReaderProvider>
  );
}

useVerseSelection

Accesses verse selection state from VerseSelectionProvider.
Requires VerseSelectionProvider to be present in the component tree.

Returns

selectedVerseUsfms
Set<string>
Set of selected verse USFM identifiers
toggleVerse
(usfm: string) => void
Toggle verse selection state
isSelected
(usfm: string) => boolean
Check if a verse is currently selected
clearSelection
() => void
Clear all selected verses
selectedCount
number
Number of currently selected verses

Usage

See VerseSelectionProvider documentation for complete usage examples.

Utility Functions

extractTextFromHtml

Extracts plain text from HTML verse content, removing markup for labels, footnotes, etc.
html
string
required
HTML content to extract text from

Returns

text
string
Plain text with normalized whitespace

Usage

import { extractTextFromHtml, useVerse } from '@youversion/platform-react-hooks';

function PlainTextVerse({ versionId, book, chapter, verse }) {
  const { verse: verseData } = useVerse(versionId, book, chapter, verse);
  
  if (!verseData) return null;
  
  const plainText = extractTextFromHtml(verseData.content);
  
  return (
    <div>
      <p>{plainText}</p>
      <button onClick={() => navigator.clipboard.writeText(plainText)}>
        Copy Text
      </button>
    </div>
  );
}

extractVersesFromHTML

Splits passage HTML into individual verse segments with verse numbers.
html
string | null | undefined
required
Passage HTML content (from usePassage or useChapter)

Returns

verses
{ verse: number; html: string }[]
Array of verse objects with verse number and HTML content

Usage

import { extractVersesFromHTML, useChapter } from '@youversion/platform-react-hooks';

function VerseByVerseView({ versionId, book, chapterNum }) {
  const { chapter } = useChapter(versionId, book, chapterNum);
  
  const verses = extractVersesFromHTML(chapter?.content);
  
  return (
    <div>
      {verses.map(({ verse, html }) => (
        <div key={verse} className="verse">
          <span className="verse-number">{verse}</span>
          <span dangerouslySetInnerHTML={{ __html: html }} />
        </div>
      ))}
    </div>
  );
}

getDayOfYear

Calculates the day of year (1-366) from a Date object. Useful for useVOTD.
date
Date
required
Date to calculate day of year for

Returns

dayOfYear
number
Day of year (1-366)

Usage

import { getDayOfYear, useVOTD } from '@youversion/platform-react-hooks';

function TodaysVerse() {
  const today = getDayOfYear(new Date());
  const { data: votd, loading } = useVOTD(today);
  
  if (loading) return <div>Loading...</div>;
  
  return (
    <div>
      <h2>Verse of the Day</h2>
      <p>{votd?.verse.text}</p>
    </div>
  );
}

Best Practices

Choose debounce delays based on the use case:
// Search input - 300ms (balance responsiveness and API calls)
const debouncedSearch = useDebounce(search, 300);

// Auto-save - 1000ms (reduce save frequency)
const debouncedContent = useDebounce(content, 1000);

// Resize handler - 150ms (quick response to resize)
const debouncedWidth = useDebounce(width, 150);
Use useMemo when extracting verses to avoid unnecessary re-parsing:
import { useMemo } from 'react';

const verses = useMemo(
  () => extractVersesFromHTML(chapter?.content),
  [chapter?.content]
);
Utility functions handle null/undefined, but always check results:
const verses = extractVersesFromHTML(chapter?.content);

if (verses.length === 0) {
  return <div>No verses found</div>;
}
// Debounced search + filtered versions + verse extraction
function AdvancedSearch() {
  const [search, setSearch] = useState('');
  const debouncedSearch = useDebounce(search, 300);
  const { versions } = useVersions('en');
  const filtered = useFilteredVersions(versions?.data || [], debouncedSearch, '*');
  
  // ...
}

Build docs developers (and LLMs) love