@bubblydoo/its-fine
v1.0.10-bubblydoo.0
Published
A collection of escape hatches for React.
Downloads
6
Readme
its-fine
A collection of escape hatches exploring React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
. I'm sure you want me to tell you how safe and stable this all is.
As such, you can go beyond React's component abstraction; components are self-aware and can tap into the React Fiber tree. This enables powerful abstractions like stateless queries and sharing React Context across concurrent renderers.
Table of Contents
Components
FiberProvider
A react-internal Fiber
provider. This component binds React children to the React Fiber tree. Call its-fine hooks within this.
Note: pmndrs renderers like react-three-fiber implement this internally to make use of
useContextBridge
, so you would only need this when using hooks inside ofreact-dom
orreact-native
.
import * as ReactDOM from 'react-dom/client'
import { FiberProvider, useFiber } from 'its-fine'
function App() {
const fiber = useFiber()
}
createRoot(document.getElementById('root')!).render(
<FiberProvider>
<App />
</FiberProvider>,
)
Hooks
Useful React hook abstractions for manipulating and querying from a component. These must be called within a FiberProvider
component.
useFiber
Returns the current react-internal Fiber
. This is an implementation detail of react-reconciler.
import * as React from 'react'
import { type Fiber, useFiber } from 'its-fine'
function Component() {
// Returns the current component's react-internal Fiber
const fiber: Fiber<null> | undefined = useFiber()
// function Component() {}
if (fiber) console.log(fiber.type)
}
useContainer
Returns the current react-reconciler container info passed to Reconciler.createContainer
.
In react-dom, a container will point to the root DOM element; in react-three-fiber, it will point to the root Zustand store.
import * as React from 'react'
import { useContainer } from 'its-fine'
function Component() {
// Returns the current renderer's root container
const container: HTMLDivElement | undefined = useContainer<HTMLDivElement>()
// <div> (e.g. react-dom)
if (container) console.log(container)
}
useNearestChild
Returns the nearest react-reconciler child instance or the node created from Reconciler.createInstance
.
In react-dom, this would be a DOM element; in react-three-fiber this would be an Instance
descriptor.
import * as React from 'react'
import { useNearestChild } from 'its-fine'
function Component() {
// Returns a React Ref which points to the nearest child <div /> element.
// Omit the element type to match the nearest element of any kind
const childRef: React.MutableRefObject<HTMLDivElement | undefined> = useNearestChild<HTMLDivElement>('div')
// Access child Ref on mount
React.useEffect(() => {
// <div> (e.g. react-dom)
const child = childRef.current
if (child) console.log(child)
}, [])
// A child element, can live deep down another component
return <div />
}
useNearestParent
Returns the nearest react-reconciler parent instance or the node created from Reconciler.createInstance
.
In react-dom, this would be a DOM element; in react-three-fiber this would be an instance descriptor.
import * as React from 'react'
import { useNearestParent } from 'its-fine'
function Component() {
// Returns a React Ref which points to the nearest parent <div /> element.
// Omit the element type to match the nearest element of any kind
const parentRef: React.MutableRefObject<HTMLDivElement | undefined> = useNearestParent<HTMLDivElement>('div')
// Access parent Ref on mount
React.useEffect(() => {
// <div> (e.g. react-dom)
const parent = parentRef.current
if (parent) console.log(parent)
}, [])
}
// A parent element wrapping Component, can live deep up another component
;<div>
<Component />
</div>
useContextBridge
React Context currently cannot be shared across React renderers but explicitly forwarded between providers (see react#17275). This hook returns a ContextBridge
of live context providers to pierce Context across renderers.
Pass ContextBridge
as a component to a secondary renderer to enable context-sharing within its children.
import * as React from 'react'
// react-nil is a secondary renderer that is usually used for testing.
// This also includes Fabric, react-three-fiber, etc
import * as ReactNil from 'react-nil'
// react-dom is a primary renderer that works on top of a secondary renderer.
// This also includes react-native, react-pixi, etc.
import * as ReactDOM from 'react-dom/client'
import { type ContextBridge, useContextBridge, FiberProvider } from 'its-fine'
function Canvas(props: { children: React.ReactNode }) {
// Returns a bridged context provider that forwards context
const Bridge: ContextBridge = useContextBridge()
// Renders children with bridged context into a secondary renderer
ReactNil.render(<Bridge>{props.children}</Bridge>)
}
// A React Context whose provider lives in react-dom
const DOMContext = React.createContext<string>(null!)
// A component that reads from DOMContext
function Component() {
// "Hello from react-dom"
console.log(React.useContext(DOMContext))
}
// Renders into a primary renderer like react-dom or react-native,
// DOMContext wraps Canvas and is bridged into Component
ReactDOM.createRoot(document.getElementById('root')!).render(
<FiberProvider>
<DOMContext.Provider value="Hello from react-dom">
<Canvas>
<Component />
</Canvas>
</DOMContext.Provider>
</FiberProvider>,
)
Utils
Additional exported utility functions for raw handling of Fibers.
traverseFiber
Traverses up or down a Fiber
, return true
to stop and select a node.
import { type Fiber, traverseFiber } from 'its-fine'
// Traverses through the Fiber tree, returns the current node when `true` is passed via selector
const parentDiv: Fiber<HTMLDivElement> | undefined = traverseFiber<HTMLDivElement>(
// Input Fiber to traverse
fiber as Fiber,
// Whether to ascend and walk up the tree. Will walk down if `false`
true,
// A Fiber node selector, returns the first match when `true` is passed
(node: Fiber<HTMLDivElement | null>) => node.type === 'div',
)