{"id":21527799,"url":"https://github.com/uvacoder/use-descendants-hook","last_synced_at":"2025-03-17T18:43:47.451Z","repository":{"id":103087603,"uuid":"537267042","full_name":"Uvacoder/use-descendants-hook","owner":"Uvacoder","description":null,"archived":false,"fork":false,"pushed_at":"2022-09-16T01:43:55.000Z","size":107,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-24T06:08:36.100Z","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/Uvacoder.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}},"created_at":"2022-09-16T01:43:44.000Z","updated_at":"2022-09-16T14:52:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"9e817235-c8fc-407f-9ed1-810b98d1b8d3","html_url":"https://github.com/Uvacoder/use-descendants-hook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Uvacoder%2Fuse-descendants-hook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Uvacoder%2Fuse-descendants-hook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Uvacoder%2Fuse-descendants-hook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Uvacoder%2Fuse-descendants-hook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Uvacoder","download_url":"https://codeload.github.com/Uvacoder/use-descendants-hook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244091303,"owners_count":20396593,"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-24T01:50:15.765Z","updated_at":"2025-03-17T18:43:47.429Z","avatar_url":"https://github.com/Uvacoder.png","language":"JavaScript","readme":"# useDescendants ![npm bundle size](https://img.shields.io/bundlephobia/minzip/use-descendants@beta)\n\n\u003e This is the README for beta releases. The \"stable\" (but still v0) release is here: https://github.com/pacocoursey/use-descendants/tree/v0\n\nuseDescendants is a react hook for keeping track of descendant components and their relative indeces. It's based off the [@reach/descendants](https://www.npmjs.com/package/@reach/descendants) package, but faster and smaller.\n\nIf you want to understand more about what this package does or why we need it, read the [Problem Complex](https://www.npmjs.com/package/@reach/descendants) from the @reach/descendants package.\n\nIn short, this package allows each item in a list to know it's relative index and the parent of the list can keep track of each child, without needing to render in a loop and pass each component an index.\n\nThis enables component composition:\n\n```js\n\u003cList\u003e\n  \u003cItem /\u003e {/* I'm index 0 */}\n  \u003cItem /\u003e {/* I'm index 1 */}\n  \u003cdiv\u003e\n    \u003cdiv\u003e\n      \u003cItem /\u003e {/* I'm arbitrarily nested, but still know that I'm index 2 */}\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/List\u003e\n```\n\n## Installation\n\n```\n$ yarn add use-descendants@beta\n```\n\n## Usage\n\nIn the parent, you call `useDescendants` and pass the result to `\u003cDescendants\u003e` that wraps the children. In each child item, retrieve that items index with the `useDescendant` hook.\n\n```jsx\nconst Menu = () =\u003e {\n  const context = useDescendants()\n  return (\n    \u003cDescendants value={context}\u003e\n      \u003cItem /\u003e\n    \u003c/Descendants\u003e\n  )\n}\n\nconst Item = () =\u003e {\n  const index = useDescendant()\n  return \u003cdiv\u003eMy index is {index}\u003c/div\u003e\n}\n```\n\n#### React.memo\n\nItems that use `React.memo` or stable keys will still have an up-to-date index, as they will be forcefully re-rendered whenever the parent re-renders. This means you can safely remove `React.memo`, as it will always be bypassed.\n\n#### Data passing\n\nYou can pass any data you want to `useDescendant` and it will be available in the parent through `map`:\n\n```jsx\n// In Item\nconst ref = useRef()\nconst index = useDescendant({ ref })\n\n// In Menu\nconst context = useDescendants()\nconsole.log(context.map.current)\n// =\u003e { '\u003crandomItemId\u003e': { index: 0, props: { ref: HTMLDivElement } } }\n```\n\nYou can also pass un-memoized values or callbacks that are always up-to-date here because it's just kept in a ref:\n\n```jsx\nconst index = useDescendant({\n  onSelect: () =\u003e {\n    /* Do something */\n  }\n})\n```\n\n## Credits\n\n- [@reach/descendants](https://www.npmjs.com/package/@reach/descendants) and [Chance](https://twitter.com/chancethedev), who introduced me to this concept\n- [Shu Ding](https://twitter.com/shuding_) for help with a faster, simpler implementation\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuvacoder%2Fuse-descendants-hook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuvacoder%2Fuse-descendants-hook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuvacoder%2Fuse-descendants-hook/lists"}