{"id":15379312,"url":"https://github.com/yaireo/react-ref-watcher","last_synced_at":"2025-04-15T17:34:13.032Z","repository":{"id":46734868,"uuid":"515605377","full_name":"yairEO/react-ref-watcher","owner":"yairEO","description":"Watchable refs changes with conditional re-renders","archived":false,"fork":false,"pushed_at":"2023-07-20T00:10:09.000Z","size":3570,"stargazers_count":6,"open_issues_count":5,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T05:06:53.850Z","etag":null,"topics":["context","hooks","react","reactjs","state","useref"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/ref-change-listener-m5bupr?file=/src/List.js","language":"JavaScript","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/yairEO.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-19T13:52:06.000Z","updated_at":"2023-10-07T05:06:36.000Z","dependencies_parsed_at":"2023-02-10T08:46:25.923Z","dependency_job_id":null,"html_url":"https://github.com/yairEO/react-ref-watcher","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yairEO%2Freact-ref-watcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yairEO%2Freact-ref-watcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yairEO%2Freact-ref-watcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yairEO%2Freact-ref-watcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yairEO","download_url":"https://codeload.github.com/yairEO/react-ref-watcher/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249119172,"owners_count":21215682,"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":["context","hooks","react","reactjs","state","useref"],"created_at":"2024-10-01T14:18:47.153Z","updated_at":"2025-04-15T17:34:13.008Z","avatar_url":"https://github.com/yairEO.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://codesandbox.io/s/ref-change-listener-m5bupr?file=/src/List.js\"\u003e\n    \u003cimg src=\"readme-header.svg\"/ \u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003ch3 align=\"center\"\u003e👀 Watch \u003ccode\u003eref\u003c/code\u003e changes with conditional re-renders\u003c/h3\u003e\n\u003cp align='center'\u003e(First draft - expect changes) \u003ca href='https://codesandbox.io/s/ref-change-listener-m5bupr?file=/src/List.js'\u003eLive demo\u003c/a\u003e\u003c/p\u003e\n\n---\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://codesandbox.io/s/ref-change-listener-m5bupr?file=/src/List.js\"\u003e\n    \u003cimg src='react-ref-watcher.apng'/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nUse `useRef` instead of `useState` by allowing it to be watchable, so a component can choose to act\n(re-render for example) when a change in the ref is detected.\n\nThis is helpful for keeping all the state at a top-level component, and pass it to the sub-components via *props* or *context*.\n\nThis solves the problem where a child updates a state defined at some top-level parent, which causes the parent to re-render and\npossibly all the sub-tree as well, which is useless and even harmful for performance in many situations.\n\nEach sub-component can register a listener for changes in a specific `ref` or any of its `current` property's properties\n(assuming `current` points to a mutated Object/Array).\n\n\u003cbr\u003e\n\n## Install with:\n\nUse from [CDN](https://unpkg.com/@yaireo/react-ref-watcher) / Download from this repo / [NPM](https://www.npmjs.com/package/@yaireo/react-ref-watcher)\n\n```bash\nnpm i @yaireo/react-ref-watcher -S\n```\n\n\u003cbr\u003e\u003cbr\u003e\n\n## What's in this package?\n\n### 1️⃣ `useWatchableRef`\n\n| Argument      | Type  | Info\n|---------------|-------|-------------------------------------------------------------\n| initialValue  | Any   | Same as the native `useRef`\n\nCreate a ref-like object that listens to any change in the `current` property\nand fires all registered callbacks when a change happens to the `current` property.\n\nThink of this as a regular `useRef` with the bonus of being watchable. See examples down.\n\n```js\nimport {useWatchableRef} from '@yaireo/react-ref-watcher'\n\nconst Component = () =\u003e {\n  const myRef = useWatchableRef(true)\n}\n```\n\n\u003cbr\u003e\n\n### 2️⃣ `useWatchableListener`\n\n| Argument | Type     | Info\n|----------|----------|-------------------------------------------------------------\n| ref      | Object   | an Object/Array to listen to\n| propName | String   | (optional) specific property name to watch within the `ref`\n| watcher  | function | (optional) argument, for custom watcher\n\nListens to refs changes.\nBy default will trigger a re-render in the component which is using this hook if\na change in the ref itself or specific property is detected.\n\nIn this example, assume `ref1` \u0026 `ref2` were created using `useWatchableRef`.\n\n```js\nimport {useWatchableListener} from '@yaireo/react-ref-watcher'\n\nconst Component = ({ ref1 }) =\u003e {\n  const {ref2} = useContext(MyContext) // getting a ref from somewhere up the tree\n\n  useWatchableListener(ref1) // triggers a re-render when ref1 changes (assuming the `ref1.current` is pointing now a new pointer in memory)\n  useWatchableListener(ref2.current, 'foo') // triggers a re-render when `foo` property changes in ref2.current (assuming ref2.current is an Object)\n}\n```\n\n\u003cbr\u003e\n\n### 3️⃣ `useWatchableEffect`\n\n| Argument      | Type     | Info\n|---------------|----------|-------------------------------------------------------------\n| callback      | Function | fires when a ref change detetced\n| dependencies  | Array    | array of watchable refs\n\nListen to changes in a ref **without** triggering a re-render\n\n```js\nimport {useWatchableEffect, useWatchableListener} from '@yaireo/react-ref-watcher'\n\nconst Component = ({ ref1, ref2 }) =\u003e {\n  // when `ref1` changes, run the callback\n  useWatchableEffect(() =\u003e {\n    ref2.current = ref1 === 'foo';\n  }, [ref1])\n\n  // ref2 is dependend on ref1. Only when ref2 changes the component should re-render\n  useWatchableListener(ref2)\n}\n```\n\n\u003cbr\u003e\n\n### 4️⃣ `propWatcher`\n\nUnlike the other hooks, this is a utility function which does the actual watching.\nIt adds an enumerable `__WATCHERS` property (will host callback listeners when changes detected)\non top of the argument (expected to be an *Object*) and then returns a new `proxy` which encapsulates the argument.\n\nEvery time a propery is modified or deleted (in your code) the proxy trap will fire and all\ncallback functions defined in the `__WATCHERS` property will fire.\n\nAny Object may be wrapped with `propWatcher` to become \"watchable\" (not only React refs).\n**Example of most basic usage:**\n\n```js\nimport {propWatcher} from '@yaireo/react-ref-watcher'\n\nconst watchableRef = propWatcher({ current: true })\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaireo%2Freact-ref-watcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyaireo%2Freact-ref-watcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaireo%2Freact-ref-watcher/lists"}