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.
The value to debounce (can be any type)
Delay in milliseconds before updating the debounced value
Returns
The debounced value, updated only after the delay period
Usage
Search Input
Auto-save
Resize Handler
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.
Array of Bible versions to filter
Search query to filter by title, abbreviation, or language
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
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.
Returns
True if any of version, book, or chapter data is loading
Combined error messages from version, book, and chapter requests
Object containing version, book, and chapter data when all are loaded Book metadata with chapters
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
Whether navigation to previous chapter is possible
Whether navigation to next chapter is possible
Navigate to the previous chapter (may cross book boundaries)
Navigate to the next chapter (may cross book boundaries)
Index of current chapter within the current book
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
Set of selected verse USFM identifiers
Toggle verse selection state
isSelected
(usfm: string) => boolean
Check if a verse is currently selected
Clear all selected verses
Number of currently selected verses
Usage
See VerseSelectionProvider documentation for complete usage examples.
Utility Functions
Extracts plain text from HTML verse content, removing markup for labels, footnotes, etc.
HTML content to extract text from
Returns
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 >
);
}
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
Individual Verses
With Selection
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 to calculate day of year for
Returns
Usage
Current Day
Specific Date
Date Picker
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
Use appropriate debounce delays
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 );
Handle empty/null HTML gracefully
Utility functions handle null/undefined, but always check results: const verses = extractVersesFromHTML ( chapter ?. content );
if ( verses . length === 0 ) {
return < div > No verses found </ div > ;
}
Combine utilities for powerful features
// 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 , '*' );
// ...
}