Initial project import
This commit is contained in:
56
node_modules/tunnel-rat/src/index.tsx
generated
vendored
Normal file
56
node_modules/tunnel-rat/src/index.tsx
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
import React, { ReactNode } from 'react'
|
||||
import { create, StoreApi } from 'zustand'
|
||||
import { useIsomorphicLayoutEffect } from './utils'
|
||||
|
||||
type Props = { children: React.ReactNode }
|
||||
|
||||
type State = {
|
||||
current: Array<React.ReactNode>
|
||||
version: number
|
||||
set: StoreApi<State>['setState']
|
||||
}
|
||||
|
||||
export default function tunnel() {
|
||||
const useStore = create<State>((set) => ({
|
||||
current: new Array<ReactNode>(),
|
||||
version: 0,
|
||||
set,
|
||||
}))
|
||||
|
||||
return {
|
||||
In: ({ children }: Props) => {
|
||||
const set = useStore((state) => state.set)
|
||||
const version = useStore((state) => state.version)
|
||||
|
||||
/* When this component mounts, we increase the store's version number.
|
||||
This will cause all existing rats to re-render (just like if the Out component
|
||||
were mapping items to a list.) The re-rendering will cause the final
|
||||
order of rendered components to match what the user is expecting. */
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
set((state) => ({
|
||||
version: state.version + 1,
|
||||
}))
|
||||
}, [])
|
||||
|
||||
/* Any time the children _or_ the store's version number change, insert
|
||||
the specified React children into the list of rats. */
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
set(({ current }) => ({
|
||||
current: [...current, children],
|
||||
}))
|
||||
|
||||
return () =>
|
||||
set(({ current }) => ({
|
||||
current: current.filter((c) => c !== children),
|
||||
}))
|
||||
}, [children, version])
|
||||
|
||||
return null
|
||||
},
|
||||
|
||||
Out: () => {
|
||||
const current = useStore((state) => state.current)
|
||||
return <>{current}</>
|
||||
},
|
||||
}
|
||||
}
|
||||
21
node_modules/tunnel-rat/src/utils.ts
generated
vendored
Normal file
21
node_modules/tunnel-rat/src/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
|
||||
/**
|
||||
* An SSR-friendly useLayoutEffect.
|
||||
*
|
||||
* React currently throws a warning when using useLayoutEffect on the server.
|
||||
* To get around it, we can conditionally useEffect on the server (no-op) and
|
||||
* useLayoutEffect elsewhere.
|
||||
*
|
||||
* @see https://github.com/facebook/react/issues/14927
|
||||
*/
|
||||
export const useIsomorphicLayoutEffect =
|
||||
typeof window !== 'undefined' && (window.document?.createElement || window.navigator?.product === 'ReactNative')
|
||||
? React.useLayoutEffect
|
||||
: React.useEffect
|
||||
|
||||
export function useMutableCallback<T>(fn: T) {
|
||||
const ref = React.useRef<T>(fn)
|
||||
useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn])
|
||||
return ref
|
||||
}
|
||||
Reference in New Issue
Block a user