{"id":16591910,"url":"https://github.com/danieldelcore/react-stable-ref","last_synced_at":"2025-08-15T20:52:05.832Z","repository":{"id":40717365,"uuid":"244528325","full_name":"danieldelcore/react-stable-ref","owner":"danieldelcore","description":"A set of utilities for testing against unstable references in React 🤷‍♂️","archived":false,"fork":false,"pushed_at":"2024-08-24T09:03:52.000Z","size":4921,"stargazers_count":17,"open_issues_count":20,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-08T06:34:07.377Z","etag":null,"topics":["hooks","react","reactjs","testing","testing-tools","unstable-references"],"latest_commit_sha":null,"homepage":"https://danieldelcore.github.io/react-stable-ref/","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/danieldelcore.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-03T03:01:38.000Z","updated_at":"2023-06-15T01:48:06.000Z","dependencies_parsed_at":"2024-10-26T20:29:56.608Z","dependency_job_id":"0a965007-034a-499a-a560-c97c21493ea1","html_url":"https://github.com/danieldelcore/react-stable-ref","commit_stats":{"total_commits":30,"total_committers":2,"mean_commits":15.0,"dds":"0.23333333333333328","last_synced_commit":"d0343a37b6a50d37b6df758d4ad9a9e56e8b2aec"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldelcore%2Freact-stable-ref","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldelcore%2Freact-stable-ref/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldelcore%2Freact-stable-ref/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldelcore%2Freact-stable-ref/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danieldelcore","download_url":"https://codeload.github.com/danieldelcore/react-stable-ref/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243730819,"owners_count":20338722,"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":["hooks","react","reactjs","testing","testing-tools","unstable-references"],"created_at":"2024-10-11T23:18:30.964Z","updated_at":"2025-03-15T12:30:25.521Z","avatar_url":"https://github.com/danieldelcore.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg width=\"300\" src=\"./assets/logo.png\" alt=\"Test stable references\"\u003e\n\u003c/p\u003e\n\n# react-stable-ref 🤷‍♂️\n\n[![min](https://img.shields.io/bundlephobia/min/react-stable-ref.svg)](https://www.npmjs.com/package/react-stable-ref)\n[![npm](https://img.shields.io/npm/v/react-stable-ref.svg)](https://www.npmjs.com/package/react-stable-ref)\n[![Downloads per month](https://img.shields.io/npm/dm/react-stable-ref.svg)](https://www.npmjs.com/package/react-stable-ref)\n\nYour stable reference utility library with everything you need to test, visualize and protect against the dreaded unintentional rerender 😱\n\n[Try it here](https://danieldelcore.github.io/react-stable-ref/)\n\n## Get started 🏗\n\n**Installation**\n\n`npm install --save react-stable-ref` or `yarn add react-stable-ref`\n\n## Example\n\n```jsx\nconst UnstableButton: FC\u003cButtonProps\u003e = ({ onClick, children }) =\u003e {\n    // Unstable reference (unstableArray is reassigned on every render)\n    const unstableArray = ['1', '2', '3'];\n    const stableValue = 'Im stable because im a string';\n\n    useStableRefTester(); // Triggers re-renders every second\n    useWhichDepChanged({ unstableArray, stableValue });\n    /**\n     * Will output the following to the console (or onChange if you pass it in)\n     *\n     * \u003e [useWhichDepChanged]: { unstableArray: { from: [1, 2, 3]; to: [1, 2, 3]}}\n     */\n\n    return (\n        \u003cbutton type=\"button\" onClick={onClick}\u003e\n            {children}\n        \u003c/button\u003e\n    );\n};\n```\n\n## Motivation 🧠\n\nIt's not always obvious when unstable references are passed into hooks such as `useEffect`. This can cause unnecessary rerenders, which when left unchecked can decrease the performance of your app, cause jank and ultimately degrade your user's experience 😭.\n\nThankfully the React team have already thought about this and provided [lint rules to help](https://www.npmjs.com/package/eslint-plugin-react-hooks) 🥰. But what if you're passing objects and arrays into dependency arrays which are not 'deeply' compared? How can you know for sure?\n\n`react-stable-ref` fills that gap and provides an assortment of utilities to help test, visualize and protect against the dreaded re-render 😱.\n\n## API 🤖\n\n### `useStableRefTester()`\n\nA **development only** hook, which increments state over a predefined interval, triggering rerenders in your component.\n\n**Arguments:**\n\n-   timeout: `Number` Timeout between rerenders\n\n**Returns:**\n\ncount: `Number`\n\n**Example:**\n\n```jsx\nconst UnstableButton = ({ children }) =\u003e {\n    const myArray = ['1', '2', '3'];\n\n    useStableRefTester();\n\n    useEffect(() =\u003e {\n        console.warn('I should not be called on every render');\n    }, [myArray]);\n\n    return \u003cbutton\u003e{children}\u003c/button\u003e;\n};\n```\n\n### `useWhichDepChanged()`\n\nA **development only** hook which emits (via console) which prop triggered an update. Useful when you are unsure which property changed in a `useEffect` dependency array.\n\n_Inspired by_: [useWhyDidYouUpdate](https://usehooks.com/useWhyDidYouUpdate/)\n\n**Arguments:**\n\n-   dependencies: `Object` A dependency object which mirrors the dependency array of the hook you are trying to test\n-   onChange(changedDeps): `(changedDeps: Obj) =\u003e void` A callback which is fired when a dependency is changed.\n\n**Returns:**\n\n`void`\n\n**Example:**\n\n```jsx\nconst UnstableButton = ({ children }) =\u003e {\n    const myArray = ['1', '2', '3'];\n\n    useWhichDepChanged({ myArray, children }, onChange(changedDeps) =\u003e {\n        console.log('UnstableButton: ', changedDeps); // UnstableButton: myArray\n    });\n\n    return \u003cbutton\u003e{children}\u003c/button\u003e;\n};\n```\n\n### `useRenderCount()`\n\nA hook which returns how many times it has been rendered.\n\n**Arguments:**\n\n-   initialCount: `Number` Initial counter value\n\n**Returns:**\n\n-   count: `Number` Current counter value\n\n**Example:**\n\n```jsx\nconst RenderCounter = () =\u003e {\n    const count = useRenderCount();\n\n    return \u003cbutton\u003e{count}\u003c/button\u003e;\n};\n```\n\n### `\u003cRenderCount /\u003e`\n\nA visual component that keeps track of the number of renders that have occurred.\n\n\u003cp align=\"left\"\u003e\n  \u003cimg width=\"200\" src=\"./assets/rendercount.png\" alt=\"Render count component\"\u003e\n\u003c/p\u003e\n\n**Props:**\n\n-   initialCount: `Number` Initial counter value\n-   count: `Number` Provide a count for a controlled API\n\n### `useDeeplyComparedEffect()`\n\n_Coming soon..._\n\nA react hook for deeply comparing objects and arrays passed into its dependency array.\n\n### `useCustomComparedEffect()`\n\n_Coming soon..._\n\nA react hook to allow you to provide custom methods used to comparing dependencies and trigger an effect.\n\n## Thanks 😍\n\nHuge thank you to [Pablo Stanley](https://twitter.com/pablostanley) and contributors of [Open Peeps](https://www.openpeeps.com/?ref=react-stable-ref) for the logo.\n\n## Resources\n\n-   [Introducing Hooks](https://reactjs.org/docs/hooks-intro.html)\n-   [Making Sense of React Hooks](https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889)\n-   [When to useMemo and useCallback](https://kentcdodds.com/blog/usememo-and-usecallback/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanieldelcore%2Freact-stable-ref","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanieldelcore%2Freact-stable-ref","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanieldelcore%2Freact-stable-ref/lists"}