usePrevious
zyeon/use-previousFreeHook
A hook that returns the value from one render ago, via render-time state adjustment instead of a ref+effect.
See it running
Open the demo on zyeon
ui.zyeon.ai/r/use-previousInstall it
npx shadcn@latest add https://ui.zyeon.ai/r/use-previous.jsonSource
1"use client"23import * as React from "react"45/**6 * Tracks the LAST DISTINCT value (compared with `Object.is`) — repeated7 * equal values do not advance it, so after a "flat" update `previous` still8 * holds the value from before the last real change (which is exactly what9 * direction indicators want). Returns `undefined` on the very10 * first render — there is no "previous" before the first one.11 *12 * Implementation note: this is deliberately NOT the classic13 * `useRef` + `useEffect` version (`ref.current = value` written inside an14 * effect, read back during render). That version only updates the ref after15 * the effect has run, so what a given render reads back is "whatever the16 * last effect happened to leave behind" — under StrictMode's double-invoke17 * or an interrupted/resumed concurrent render, it is not well-defined which18 * pass wrote the ref last. It also means reading a ref's `.current` during19 * render, which this repo's lint setup treats as a smell (render should stay20 * pure; ref reads/writes belong in effects or event handlers, not scattered21 * across both).22 *23 * Here both the current and the previous value live in state, and the24 * comparison happens during render itself: if `value` changed (checked with25 * `Object.is`, the same equality React uses for its own bailout checks) this26 * render calls `setState` to shift the old current into previous — the27 * official React "adjust state during render" pattern, not a forbidden28 * effect-body `setState`. Because the update happens inside the same render29 * pass that noticed the change, the ordering is deterministic regardless of30 * StrictMode or concurrent re-renders, and it never touches a ref outside of31 * an effect.32 */33export function usePrevious<T>(value: T): T | undefined {34 const [state, setState] = React.useState<{ current: T; previous: T | undefined }>({35 current: value,36 previous: undefined,37 })3839 if (!Object.is(state.current, value)) {40 setState({ current: value, previous: state.current })41 }4243 return state.previous44}4546export default usePrevious
Files it writes
More from zyeon
All 517 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| useAsyncuse-async | zyeon | Hooks | Free | no deps | |
| useBroadcastChanneluse-broadcast-channel | zyeon | Hooks | Free | no deps | |
| useClickOutsideuse-click-outside | zyeon | Hooks | Free | no deps | |
| useClipboardPasteuse-clipboard-paste | zyeon | Hooks | Free | no deps | |
| useControllableStateuse-controllable-state | zyeon | Hooks | Free | no deps | |
| useCopyToClipboarduse-copy-to-clipboard | zyeon | Hooks | Free | no deps | |
| useCountdownuse-countdown | zyeon | Hooks | Free | no deps | |
| useDebounceValueuse-debounce-value | zyeon | Hooks | Free | no deps |
