pmndrs / tunnel-rat

🐀 Non gratum anus rodentum
MIT License
354 stars 9 forks source link

Alternative tunnel implementation #16

Open dennemark opened 1 year ago

dennemark commented 1 year ago

Was trying to integrate tunnel-rats into drei Html component, since it avoids creating a react-dom renderer for each element, but instead uses the existing react-dom renderer. (https://github.com/pmndrs/drei/issues/1077)

While searching for issues within the tunnel component, I came up with an even simpler interface, but different dependency @preact/signals-react

I left out the versioning so far. Also nearly got one to work that does not need any external dependency, even tried to shortly write my own state manager with useSyncExternal store 😅 but got a bit convoluted. Anyways, it seems to work the same as the zustand approach.

Only thing that I have to check, is the ordering of arrays, but if I can reproduce it, I will open another issue.

https://codesandbox.io/s/html-annotations-forked-p89h6t?file=/src/HtmlTunnel.tsx

import { ReactNode, useLayoutEffect } from "react"
import { signal } from "@preact/signals-react"

export function tunnel() {
  const sig = signal([])
  return {
    Out: () => {
      return <>{sig.value}</>
    },
    In: ({ children }: { children: ReactNode }) => {
      useLayoutEffect(() => {
        sig.value = [...sig.value, children]
        return () => {
          sig.value = sig.value.filter((x) => x !== children)
        }
      }, [children])
      return <></>
    }
  }
}
dennemark commented 1 year ago

Concerning the reordering of array, there is actually really an issue. Since useFrame renders more often than react, the order of elements can change, when an array is used. I don´t have a sandbox setting right now, but I had to implement an object store, instead of arrays for the children.

Am using a uuid for convenience in the In store: https://codesandbox.io/s/html-annotations-forked-sb1cku?file=/src/Tunnel.tsx