{"id":18530954,"url":"https://github.com/jonabrams/eslint-plugin-react-hooks-signals","last_synced_at":"2025-06-25T05:42:23.189Z","repository":{"id":216440596,"uuid":"741343814","full_name":"JonAbrams/eslint-plugin-react-hooks-signals","owner":"JonAbrams","description":"A modified version of React's official eslint plugin for projects that use Signals","archived":false,"fork":false,"pushed_at":"2024-02-10T22:54:58.000Z","size":146,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-09T14:07:06.790Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JonAbrams.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2024-01-10T07:44:59.000Z","updated_at":"2024-02-21T13:02:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"179d1f0a-7633-45f0-81fa-dfc976066630","html_url":"https://github.com/JonAbrams/eslint-plugin-react-hooks-signals","commit_stats":null,"previous_names":["jonabrams/eslint-plugin-react-hooks-signals"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Feslint-plugin-react-hooks-signals","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Feslint-plugin-react-hooks-signals/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Feslint-plugin-react-hooks-signals/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Feslint-plugin-react-hooks-signals/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JonAbrams","download_url":"https://codeload.github.com/JonAbrams/eslint-plugin-react-hooks-signals/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254235701,"owners_count":22036964,"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":[],"created_at":"2024-11-06T18:04:37.807Z","updated_at":"2025-06-25T05:42:23.177Z","avatar_url":"https://github.com/JonAbrams.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `eslint-plugin-react-hooks-signals`\n\nThis ESLint plugin is a modified version of React's official [hooks plugin](https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks). This provides a new rule called \"exhaustive-deps-signals\" that is intended to be used instead of React's \"exhaustive-deps\" if you use [@preact/signals-react](https://github.com/preactjs/signals/tree/main/packages/react) in your project.\n\nYou should still include React's eslint hooks plugin since it provides the \"rules-of-hooks\" eslint rule, but you should disable their version of \"exhaustive-deps\".\n\n## Installation\n\n```sh\n# npm\nnpm install -D eslint-plugin-react-hooks-signals\n# yarn\nyarn add -D eslint-plugin-react-hooks-signals\n```\n\n## Example `.eslintrc.js`\n\n```js\nmodule.exports = {\n  …,\n  extends: [\n    …,\n    'plugin:react-hooks-signals/recommended',\n  ],\n  rules: {\n    …,\n    'react-hooks/exhaustive-deps': 'off',\n  }\n}\n```\n\n## Explanation\n\nThe official React lint rule \"react-hooks/exhaustive-deps\" doesn't play nicely with signals.\n\nConsider this example:\n\n```jsx\nimport { signal } from \"@preact/signals-react\";\nconst countSignal = signal(0);\n\nexport function Counter({ multiplier: number }) {\n  useEffect(() =\u003e {\n    localStorage.setItem(\n      \"countWithMultiplier\",\n      `${multiplier * countSignal.value}`\n    );\n  }, [multiple, countSignal.value]);\n\n  return (\n    \u003cdiv\u003e\n      {multiplier * countSignal.value}\n      \u003cbutton onClick={() =\u003e countSignal.value++}\u003eAdd One\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nThe above will fail the \"react-hooks/exhaustive-deps\" check because `countSignal.value` in the list of useEffect dependencies is declared an error:\n\n\u003e Outer scope values like 'countSignal.value' aren't valid dependencies because mutating them doesn't re-render the component.\n\nBut with signals it _does_ re-render the component, so it should be a valid dependency!\n\nThis eslint plugin provides a rule that does two things different:\n\n1. It knows that externally declared signals can re-render a component, so its values should be in the dependency array when used in an effect.\n2. It understands that depending on a signal isn't enough, the signal's value needs to be depended on, since the signal container doesn't change when the signal's value update.\n\nIn addition to the above, it provides all the existing checks of React's eslint rule, so you should turn off React's \"exhaustive-deps\" rule to keep this rule from conflicting.\n\n## Advanced Configuration\n\n`exhaustive-deps-signals` can be configured to validate dependencies of custom Hooks with the `additionalHooks` option.\nThis option accepts a regex to match the names of custom Hooks that have dependencies.\n\n```js\n{\n  \"rules\": {\n    // ...\n    \"react-hooks-signals/exhaustive-deps-signals\": [\"warn\", {\n      \"additionalHooks\": \"(useMyCustomHook|useMyOtherCustomHook)\"\n    }]\n  }\n}\n```\n\nThe React Devs suggest to use this option **very sparingly, if at all**. Generally saying, they recommend most custom Hooks to not use the dependencies argument, and instead provide a higher-level API that is more focused around a specific use case.\n\n## License\n\nMIT\n\n## Attribution\n\nModified by Jon Abrams, based on the existing code by Facebook.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonabrams%2Feslint-plugin-react-hooks-signals","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonabrams%2Feslint-plugin-react-hooks-signals","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonabrams%2Feslint-plugin-react-hooks-signals/lists"}