{"id":13902794,"url":"https://github.com/pmndrs/its-fine","last_synced_at":"2025-05-13T00:10:24.064Z","repository":{"id":58563473,"uuid":"532479550","full_name":"pmndrs/its-fine","owner":"pmndrs","description":"🐶🔥 A collection of escape hatches for React.","archived":false,"fork":false,"pushed_at":"2025-02-18T15:45:41.000Z","size":1434,"stargazers_count":1103,"open_issues_count":0,"forks_count":12,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-10T10:36:45.265Z","etag":null,"topics":["fiber","hooks","internal","react","reconciler"],"latest_commit_sha":null,"homepage":"https://npmjs.com/its-fine","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/pmndrs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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,"zenodo":null},"funding":{"github":["CodyJasonBennett"]}},"created_at":"2022-09-04T08:21:42.000Z","updated_at":"2025-05-06T19:27:54.000Z","dependencies_parsed_at":"2024-01-23T22:08:49.777Z","dependency_job_id":"09d048ed-de47-48fd-86ae-b80f3711e01f","html_url":"https://github.com/pmndrs/its-fine","commit_stats":{"total_commits":93,"total_committers":7,"mean_commits":"13.285714285714286","dds":0.4731182795698925,"last_synced_commit":"598b81f02778c22ed21121c2b1a786bdefb14e23"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fits-fine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fits-fine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fits-fine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fits-fine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmndrs","download_url":"https://codeload.github.com/pmndrs/its-fine/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253650948,"owners_count":21942232,"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":["fiber","hooks","internal","react","reconciler"],"created_at":"2024-08-06T22:01:24.568Z","updated_at":"2025-05-13T00:10:24.026Z","avatar_url":"https://github.com/pmndrs.png","language":"TypeScript","funding_links":["https://github.com/sponsors/CodyJasonBennett"],"categories":["TypeScript"],"sub_categories":[],"readme":"# its-fine\n\n[![Size](https://img.shields.io/bundlephobia/minzip/its-fine?label=gzip\u0026style=flat\u0026colorA=000000\u0026colorB=000000)](https://bundlephobia.com/package/its-fine)\n[![Version](https://img.shields.io/npm/v/its-fine?style=flat\u0026colorA=000000\u0026colorB=000000)](https://npmjs.com/package/its-fine)\n[![Downloads](https://img.shields.io/npm/dt/its-fine.svg?style=flat\u0026colorA=000000\u0026colorB=000000)](https://npmjs.com/package/its-fine)\n[![Twitter](https://img.shields.io/twitter/follow/pmndrs?label=%40pmndrs\u0026style=flat\u0026colorA=000000\u0026colorB=000000\u0026logo=twitter\u0026logoColor=000000)](https://twitter.com/pmndrs)\n[![Discord](https://img.shields.io/discord/740090768164651008?style=flat\u0026colorA=000000\u0026colorB=000000\u0026label=discord\u0026logo=discord\u0026logoColor=000000)](https://discord.gg/poimandres)\n\n\u003cp align=\"left\"\u003e\n  \u003ca id=\"cover\" href=\"#cover\"\u003e\n    \u003cimg src=\".github/itsfine.jpg\" alt=\"It's gonna be alright\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nA collection of escape hatches for React.\n\nAs such, you can go beyond React's component abstraction; components are self-aware and can tap into the [React Fiber](https://youtu.be/ZCuYPiUIONs) tree. This enables powerful abstractions that can modify or extend React behavior without explicitly taking reconciliation into your own hands.\n\n## Table of Contents\n\n- [Components](#components)\n  - [FiberProvider](#fiberprovider)\n- [Hooks](#hooks)\n  - [useFiber](#useFiber)\n  - [useContainer](#useContainer)\n  - [useNearestChild](#useNearestChild)\n  - [useNearestParent](#useNearestParent)\n  - [useContextMap](#useContextMap)\n  - [useContextBridge](#useContextBridge)\n- [Utils](#utils)\n  - [traverseFiber](#traverseFiber)\n\n## Components\n\n### FiberProvider\n\nA react-internal `Fiber` provider. This component binds React children to the React Fiber tree. Call its-fine hooks within this.\n\n\u003e **Note**: pmndrs renderers like react-three-fiber implement this internally to make use of [`useContextBridge`](#usecontextbridge), so you would only need this when using hooks inside of `react-dom` or `react-native`.\n\n```tsx\nimport * as ReactDOM from 'react-dom/client'\nimport { FiberProvider, useFiber } from 'its-fine'\n\nfunction App() {\n  const fiber = useFiber()\n}\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n  \u003cFiberProvider\u003e\n    \u003cApp /\u003e\n  \u003c/FiberProvider\u003e,\n)\n```\n\n## Hooks\n\nUseful React hook abstractions for manipulating and querying from a component. These must be called within a [`FiberProvider`](#fiberprovider) component.\n\n### useFiber\n\nReturns the current react-internal `Fiber`. This is an implementation detail of [react-reconciler](https://github.com/facebook/react/tree/main/packages/react-reconciler).\n\n```tsx\nimport * as React from 'react'\nimport { type Fiber, useFiber } from 'its-fine'\n\nfunction Component() {\n  // Returns the current component's react-internal Fiber\n  const fiber: Fiber\u003cnull\u003e | undefined = useFiber()\n\n  // function Component() {}\n  if (fiber) console.log(fiber.type)\n}\n```\n\n### useContainer\n\nReturns the current react-reconciler container info passed to `Reconciler.createContainer`.\n\nIn react-dom, a container will point to the root DOM element; in react-three-fiber, it will point to the root Zustand store.\n\n```tsx\nimport * as React from 'react'\nimport { useContainer } from 'its-fine'\n\nfunction Component() {\n  // Returns the current renderer's root container\n  const container: HTMLDivElement | undefined = useContainer\u003cHTMLDivElement\u003e()\n\n  // \u003cdiv\u003e (e.g. react-dom)\n  if (container) console.log(container)\n}\n```\n\n### useNearestChild\n\nReturns the nearest react-reconciler child instance or the node created from `Reconciler.createInstance`.\n\nIn react-dom, this would be a DOM element; in react-three-fiber this would be an `Instance` descriptor.\n\n```tsx\nimport * as React from 'react'\nimport { useNearestChild } from 'its-fine'\n\nfunction Component() {\n  // Returns a React Ref which points to the nearest child \u003cdiv /\u003e element.\n  // Omit the element type to match the nearest element of any kind\n  const childRef: React.MutableRefObject\u003cHTMLDivElement | undefined\u003e = useNearestChild\u003cHTMLDivElement\u003e('div')\n\n  // Access child Ref on mount\n  React.useEffect(() =\u003e {\n    // \u003cdiv\u003e (e.g. react-dom)\n    const child = childRef.current\n    if (child) console.log(child)\n  }, [])\n\n  // A child element, can live deep down another component\n  return \u003cdiv /\u003e\n}\n```\n\n### useNearestParent\n\nReturns the nearest react-reconciler parent instance or the node created from `Reconciler.createInstance`.\n\nIn react-dom, this would be a DOM element; in react-three-fiber this would be an instance descriptor.\n\n```tsx\nimport * as React from 'react'\nimport { useNearestParent } from 'its-fine'\n\nfunction Component() {\n  // Returns a React Ref which points to the nearest parent \u003cdiv /\u003e element.\n  // Omit the element type to match the nearest element of any kind\n  const parentRef: React.MutableRefObject\u003cHTMLDivElement | undefined\u003e = useNearestParent\u003cHTMLDivElement\u003e('div')\n\n  // Access parent Ref on mount\n  React.useEffect(() =\u003e {\n    // \u003cdiv\u003e (e.g. react-dom)\n    const parent = parentRef.current\n    if (parent) console.log(parent)\n  }, [])\n}\n\n// A parent element wrapping Component, can live deep up another component\n;\u003cdiv\u003e\n  \u003cComponent /\u003e\n\u003c/div\u003e\n```\n\n### useContextMap\n\nReturns a map of all contexts and their values.\n\n```tsx\nimport * as React from 'react'\nimport { useContextMap } from 'its-fine'\n\nconst SomeContext = React.createContext\u003cstring\u003e(null!)\n\nfunction Component() {\n  const contextMap = useContextMap()\n  return contextMap.get(SomeContext)\n}\n```\n\n### useContextBridge\n\nReact Context currently cannot be shared across [React renderers](https://reactjs.org/docs/codebase-overview.html#renderers) but explicitly forwarded between providers (see [react#17275](https://github.com/facebook/react/issues/17275)). This hook returns a `ContextBridge` of live context providers to pierce Context across renderers.\n\nPass `ContextBridge` as a component to a secondary renderer to enable context-sharing within its children.\n\n```tsx\nimport * as React from 'react'\n// react-nil is a secondary renderer that is usually used for testing.\n// This also includes Fabric, react-three-fiber, etc\nimport * as ReactNil from 'react-nil'\n// react-dom is a primary renderer that works on top of a secondary renderer.\n// This also includes react-native, react-pixi, etc.\nimport * as ReactDOM from 'react-dom/client'\nimport { type ContextBridge, useContextBridge, FiberProvider } from 'its-fine'\n\nfunction Canvas(props: { children: React.ReactNode }) {\n  // Returns a bridged context provider that forwards context\n  const Bridge: ContextBridge = useContextBridge()\n  // Renders children with bridged context into a secondary renderer\n  ReactNil.render(\u003cBridge\u003e{props.children}\u003c/Bridge\u003e)\n}\n\n// A React Context whose provider lives in react-dom\nconst DOMContext = React.createContext\u003cstring\u003e(null!)\n\n// A component that reads from DOMContext\nfunction Component() {\n  // \"Hello from react-dom\"\n  console.log(React.useContext(DOMContext))\n}\n\n// Renders into a primary renderer like react-dom or react-native,\n// DOMContext wraps Canvas and is bridged into Component\nReactDOM.createRoot(document.getElementById('root')!).render(\n  \u003cFiberProvider\u003e\n    \u003cDOMContext.Provider value=\"Hello from react-dom\"\u003e\n      \u003cCanvas\u003e\n        \u003cComponent /\u003e\n      \u003c/Canvas\u003e\n    \u003c/DOMContext.Provider\u003e\n  \u003c/FiberProvider\u003e,\n)\n```\n\n## Utils\n\nAdditional exported utility functions for raw handling of Fibers.\n\n### traverseFiber\n\nTraverses up or down a `Fiber`, return `true` to stop and select a node.\n\n```ts\nimport { type Fiber, traverseFiber } from 'its-fine'\n\n// Traverses through the Fiber tree, returns the current node when `true` is passed via selector\nconst parentDiv: Fiber\u003cHTMLDivElement\u003e | undefined = traverseFiber\u003cHTMLDivElement\u003e(\n  // Input Fiber to traverse\n  fiber as Fiber,\n  // Whether to ascend and walk up the tree. Will walk down if `false`\n  true,\n  // A Fiber node selector, returns the first match when `true` is passed\n  (node: Fiber\u003cHTMLDivElement | null\u003e) =\u003e node.type === 'div',\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmndrs%2Fits-fine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmndrs%2Fits-fine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmndrs%2Fits-fine/lists"}