{"id":19451216,"url":"https://github.com/thekashey/use-callback-ref","last_synced_at":"2025-05-14T06:11:49.656Z","repository":{"id":35812034,"uuid":"193071236","full_name":"theKashey/use-callback-ref","owner":"theKashey","description":"🤙The same useRef, but it will callback","archived":false,"fork":false,"pushed_at":"2024-12-17T11:08:37.000Z","size":1104,"stargazers_count":308,"open_issues_count":17,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-07T18:03:41.329Z","etag":null,"topics":["callback","hooks","react","ref","useref"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/usecallbackref-example-jldvr","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theKashey.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-21T09:33:14.000Z","updated_at":"2025-04-07T08:12:15.000Z","dependencies_parsed_at":"2024-06-18T13:39:42.893Z","dependency_job_id":"bc6d4ca3-97f9-4018-8316-13ce31ea5e92","html_url":"https://github.com/theKashey/use-callback-ref","commit_stats":{"total_commits":44,"total_committers":4,"mean_commits":11.0,"dds":0.06818181818181823,"last_synced_commit":"df9da0fedf6eb89f454b32a986049a511e504a1d"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fuse-callback-ref","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fuse-callback-ref/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fuse-callback-ref/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fuse-callback-ref/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theKashey","download_url":"https://codeload.github.com/theKashey/use-callback-ref/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248960107,"owners_count":21189978,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["callback","hooks","react","ref","useref"],"created_at":"2024-11-10T16:40:46.105Z","updated_at":"2025-04-14T20:43:13.081Z","avatar_url":"https://github.com/theKashey.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003e🤙 use-callback-ref 📞\u003c/h1\u003e\n  \u003cbr/\u003e\n  The same `useRef` but it will callback: 📞 Hello! Your ref was changed!\n  \u003cbr/\u003e\n    \u003ca href=\"https://www.npmjs.com/package/use-callback-ref\"\u003e\n      \u003cimg src=\"https://img.shields.io/npm/v/use-callback-ref.svg?style=flat-square\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://travis-ci.org/theKashey/use-callback-ref\"\u003e\n       \u003cimg alt=\"Travis\" src=\"https://img.shields.io/travis/theKashey/use-callback-ref/master.svg?style=flat-square\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://bundlephobia.com/result?p=use-callback-ref\"\u003e\n      \u003cimg src=\"https://img.shields.io/bundlephobia/minzip/use-callback-ref.svg\" alt=\"bundle size\"\u003e\n    \u003c/a\u003e \n\u003c/div\u003e\n\n---\n\n\u003e Keep in mind that useRef doesn't notify you when its content changes.\n\u003e Mutating the .current property doesn't cause a re-render.\n\u003e If you want to run some code when React attaches or detaches a ref to a DOM node,\n\u003e you may want to use ~~a callback ref instead~~ .... **useCallbackRef** instead.\n\n– [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html#useref)\n\nRead more about `use-callback` pattern and use cases:\n\n- https://dev.to/thekashey/the-same-useref-but-it-will-callback-8bo\n\nThis library exposes helpers to handle any case related to `ref` _lifecycle_\n\n- `useCallbackRef` - react on a ref change (replacement for `useRef`)\n  - `createCallbackRef` - - low level version of `useCallbackRef`\n- `useMergeRefs` - merge multiple refs together creating a stable return ref\n  - `mergeRefs` - low level version of `useMergeRefs`\n- `useTransformRef` - transform one ref to another (replacement for `useImperativeHandle`)\n  - `transformRef` - low level version of `useTransformRef`\n- `useRefToCallback` - convert RefObject to an old callback-style ref\n  - `refToCallback` - low level version of `useRefToCallback`\n- `assignRef` - assign value to the ref, regardless it is RefCallback or RefObject\n\nAll functions are tree shakable, but even together it's **less then 300b**.\n\n# API\n\n💡 Some commands are hooks based, and returns the same refs/functions every render.\nBut some are not, to be used in classes or non-react code.\n\n## useRef API\n\n🤔 Use case: every time you have to react to ref change\n\nAPI is 99% compatible with React `createRef` and `useRef`, and just adds another argument - `callback`,\nwhich would be called on **ref update**.\n\n#### createCallbackRef - to replace React.createRef\n\n- `createCallbackRef(callback)` - would call provided `callback` when ref is changed.\n\n#### useCallbackRef - to replace React.useRef\n\n- `useCallbackRef(initialValue, callback)` - would call provided `callback` when ref is changed.\n\n\u003e `callback` in both cases is `callback(newValue, oldValue)`. Callback would not be called if newValue and oldValue is the same.\n\n```js\nimport { useRef, createRef, useState } from 'react';\nimport { useCallbackRef, createCallbackRef } from 'use-callback-ref';\n\nconst Component = () =\u003e {\n  const [, forceUpdate] = useState();\n  // I dont need callback when ref changes\n  const ref = useRef(null);\n\n  // but sometimes - it could be what you need\n  const anotherRef = useCallbackRef(null, () =\u003e forceUpdate());\n\n  useEffect(() =\u003e {\n    // now it's just possible\n  }, [anotherRef.current]); // react to dom node change\n};\n```\n\n💡 You can use `useCallbackRef` to convert RefObject into RefCallback, creating bridges between the old and the new code\n\n```js\n// some old component\nconst onRefUpdate = (newRef) =\u003e {...}\nconst refObject = useCallbackRef(null, onRefUpdate);\n// ...\n\u003cSomeNewComponent ref={refObject}/\u003e\n```\n\n## assignRef\n\n🤔 Use case: every time you need to assign ref manually, and you dont know the shape of the ref\n\n`assignRef(ref, value)` - assigns `values` to the `ref`. `ref` could be RefObject or RefCallback.\n\n```\n🚫 ref.current = value // what if it's a callback-ref?\n🚫 ref(value) // but what if it's a object ref?\n\nimport {assignRef} from \"use-callback-ref\";\n✅ assignRef(ref, value);\n```\n\n## useTransformRef (to replace React.useImperativeHandle)\n\n🤔 Use case: ref could be different.\n`transformRef(ref, tranformer):Ref` - return a new `ref` which would propagate all changes to the provided `ref` with applied `transform`\n\n```js\n// before\nconst ResizableWithRef = forwardRef((props, ref) =\u003e \u003cResizable {...props} ref={(i) =\u003e i \u0026\u0026 ref(i.resizable)} /\u003e);\n\n// after\n\nconst ResizableWithRef = forwardRef((props, ref) =\u003e (\n  \u003cResizable {...props} ref={transformRef(ref, (i) =\u003e (i ? i.resizable : null))} /\u003e\n));\n```\n\n## refToCallback\n\n`refToCallback(ref: RefObject): RefCallback` - for compatibility between the old and the new code.\nFor the compatibility between `RefCallback` and RefObject use `useCallbackRef(undefined, callback)`\n\n## useMergeRefs\n\n`mergeRefs(refs: arrayOfRefs, [defaultValue]):ReactMutableRef` - merges a few refs together\n\nWhen developing low level UI components, it is common to have to use a local ref but also support an external one using React.forwardRef. Natively, React does not offer a way to set two refs inside the ref property. This is the goal of this small utility.\n\n```js\nimport React from 'react';\nimport { useMergeRefs } from 'use-callback-ref';\n\nconst MergedComponent = React.forwardRef((props, ref) =\u003e {\n  const localRef = React.useRef();\n  // ...\n  // both localRef and ref would be populated with the `ref` to a `div`\n  return \u003cdiv ref={useMergeRefs([localRef, ref])} /\u003e;\n});\n```\n\n💡 - `useMergeRefs` will always give you the same return, and you don't have to worry about `[localRef, ref]` unique every render.\n\n## mergeRefs\n\n`mergeRefs(refs: arrayOfRefs, [defaultValue]):ReactMutableRef` - merges a few refs together\nis a non-hook based version. Will produce the new `ref` every run, causing the old one to unmount, and be _populated_ with the `null` value.\n\n\u003e mergeRefs are based on https://github.com/smooth-code/react-merge-refs, just exposes a RefObject, instead of a callback\n\n`mergeRefs` are \"safe\" to use as a part of other hooks-based commands, but don't forget - it returns a new object every call.\n\n# Similar packages:\n\n- [apply-ref](https://github.com/mitchellhamilton/apply-ref) - `applyRefs` is simular to `mergeRef`, `applyRef` is similar to `assignRef`\n- [useForkRef](https://react-hooks.org/docs/use-fork-ref) - `useForkRef` is simular to `useMergeRefs`, but accepts only two arguments.\n- [react-merge-refs](https://github.com/gregberge/react-merge-refs) - `merge-refs` is simular to `useMergeRefs`, but not a hook and does not provide \"stable\" reference.\n\n---\n\n\u003e Is it a rocket science? No, `RefObject` is no more than `{current: ref}`, and `use-callback-ref` is no more than `getter` and `setter` on that field.\n\n# License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekashey%2Fuse-callback-ref","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthekashey%2Fuse-callback-ref","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekashey%2Fuse-callback-ref/lists"}