- Introduced comprehensive documentation for the Nostr Development Kit (NDK) including an overview, quick reference, and troubleshooting guide. - Added detailed examples covering initialization, authentication, event publishing, querying, and user profile management. - Structured the documentation to facilitate quick lookups and deep learning, based on real-world usage patterns from the Plebeian Market application. - Created an index for examples to enhance usability and navigation. - Bumped version to 1.0.0 to reflect the addition of this new skill set.
5.9 KiB
5.9 KiB
React Hooks Quick Reference
State Hooks
useState
const [state, setState] = useState<Type>(initialValue)
const [count, setCount] = useState(0)
// Functional update
setCount(prev => prev + 1)
// Lazy initialization
const [state, setState] = useState(() => expensiveComputation())
useReducer
type State = { count: number }
type Action = { type: 'increment' } | { type: 'decrement' }
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'increment': return { count: state.count + 1 }
case 'decrement': return { count: state.count - 1 }
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 })
dispatch({ type: 'increment' })
useActionState (React 19)
const [state, formAction, isPending] = useActionState(
async (previousState, formData: FormData) => {
// Server action
return await processForm(formData)
},
initialState
)
<form action={formAction}>
<button disabled={isPending}>Submit</button>
</form>
Effect Hooks
useEffect
useEffect(() => {
// Side effect
const subscription = api.subscribe()
// Cleanup
return () => subscription.unsubscribe()
}, [dependencies])
Timing: After render & paint Use for: Data fetching, subscriptions, DOM mutations
useLayoutEffect
useLayoutEffect(() => {
// Runs before paint
const height = ref.current.offsetHeight
setHeight(height)
}, [])
Timing: After render, before paint Use for: DOM measurements, preventing flicker
useInsertionEffect
useInsertionEffect(() => {
// Insert styles before any DOM reads
const style = document.createElement('style')
style.textContent = css
document.head.appendChild(style)
return () => document.head.removeChild(style)
}, [css])
Timing: Before any DOM mutations Use for: CSS-in-JS libraries
Performance Hooks
useMemo
const memoizedValue = useMemo(() => {
return expensiveComputation(a, b)
}, [a, b])
Use for: Expensive calculations, stable object references
useCallback
const memoizedCallback = useCallback(() => {
doSomething(a, b)
}, [a, b])
Use for: Passing callbacks to optimized components
Ref Hooks
useRef
// DOM reference
const ref = useRef<HTMLDivElement>(null)
ref.current?.focus()
// Mutable value (doesn't trigger re-render)
const countRef = useRef(0)
countRef.current += 1
useImperativeHandle
useImperativeHandle(ref, () => ({
focus: () => inputRef.current?.focus(),
clear: () => inputRef.current && (inputRef.current.value = '')
}), [])
Context Hook
useContext
const value = useContext(MyContext)
Must be used within a Provider.
Transition Hooks
useTransition
const [isPending, startTransition] = useTransition()
startTransition(() => {
setState(newValue) // Non-urgent update
})
useDeferredValue
const [input, setInput] = useState('')
const deferredInput = useDeferredValue(input)
// Use deferredInput for expensive operations
const results = useMemo(() => search(deferredInput), [deferredInput])
Optimistic Updates (React 19)
useOptimistic
const [optimisticState, addOptimistic] = useOptimistic(
actualState,
(currentState, optimisticValue) => {
return [...currentState, optimisticValue]
}
)
Other Hooks
useId
const id = useId()
<label htmlFor={id}>Name</label>
<input id={id} />
useSyncExternalStore
const state = useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot
)
useDebugValue
useDebugValue(isOnline ? 'Online' : 'Offline')
use (React 19)
// Read context or promise
const value = use(MyContext)
const data = use(fetchPromise) // Must be in Suspense
Form Hooks (React DOM)
useFormStatus
import { useFormStatus } from 'react-dom'
const { pending, data, method, action } = useFormStatus()
Hook Rules
- Only call at top level - Not in loops, conditions, or nested functions
- Only call from React functions - Components or custom hooks
- Custom hooks start with "use" - Naming convention
- Same hooks in same order - Every render must call same hooks
Dependencies Best Practices
- Include all used values - Variables, props, state from component scope
- Use ESLint plugin -
eslint-plugin-react-hooksenforces rules - Functions as dependencies - Wrap with useCallback or define outside component
- Object/array dependencies - Use useMemo for stable references
Common Patterns
Fetching Data
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
const controller = new AbortController()
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false))
return () => controller.abort()
}, [])
Debouncing
const [value, setValue] = useState('')
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value)
}, 500)
return () => clearTimeout(timer)
}, [value])
Previous Value
const usePrevious = <T,>(value: T): T | undefined => {
const ref = useRef<T>()
useEffect(() => {
ref.current = value
})
return ref.current
}
Interval
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1)
}, 1000)
return () => clearInterval(id)
}, [])
Event Listeners
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth)
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])