@baystream/ui-hooks
v1.0.4
Published
Small React hooks shared across Baystream UI packages.
Readme
@baystream/ui-hooks
Small React hooks shared across Baystream UI packages.
Install
npm install @baystream/ui-hooks reactExports
useStableCallback
Why this package exists
This package keeps tiny React behavior helpers separate from visual components. Import it when you want a stable callback reference without adding another utility library.
useStableCallback
Returns a callback with a stable identity whose implementation always sees the latest state and props.
This is useful when:
- passing callbacks into effects or subscriptions
- attaching listeners once and still using fresh values
- avoiding unnecessary re-subscription caused by changing callback references
Example: timer with latest state
import { useEffect, useState } from 'react'
import { useStableCallback } from '@baystream/ui-hooks'
export function AutoSaveStatus() {
const [draft, setDraft] = useState('')
const [saveCount, setSaveCount] = useState(0)
const saveDraft = useStableCallback(() => {
if (draft.trim().length === 0) {
return
}
console.log('Saving latest draft:', draft)
setSaveCount((count) => count + 1)
})
useEffect(() => {
const intervalId = window.setInterval(() => {
saveDraft()
}, 5000)
return () => window.clearInterval(intervalId)
}, [saveDraft])
return (
<div>
<textarea
value={draft}
onChange={(event) => setDraft(event.target.value)}
placeholder="Write something..."
/>
<p>Auto-saved {saveCount} times</p>
</div>
)
}Example: event listener without stale closures
import { useEffect, useState } from 'react'
import { useStableCallback } from '@baystream/ui-hooks'
export function WindowWidthLabel() {
const [width, setWidth] = useState(window.innerWidth)
const handleResize = useStableCallback(() => {
setWidth(window.innerWidth)
})
useEffect(() => {
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [handleResize])
return <span>Width: {width}px</span>
}Notes
- In the Baystream UI monorepo, the library-testing app is normally linked to local
packages/*via workspaces; you can switch it to published@baystream/*for consumer-style smoke tests — see the repository root README. - Requires React 19 or later.
- Prefer this when
useCallbackalone is not enough because the callback must always see fresh values.
