Hi! remix-three is a very tiny shim layer allowing you to render a <Canvas>
from @react-three/fiber
into a Remix app, as well as render Remix <Outlet>
s and calls to useLoaderData()
inside your <Canvas>
.
This repo consists of three things:
- A set of
patch-package
patches to make all the@react-three/*
libraries play nice with the Remix compiler. - A
useRemixBridge
utility build on@react-three/drei
'suseContextBridge
that will replay all of the necessary Remix context values into the<Canvas>
rendering fiber. - A
<Link3d>
component that allows you to have any object in your 3D scene participate in Remix navigation.
-
npm i remix-three @react-three/[email protected] @react-three/[email protected] @remix-run/[email protected] patch-package
-
Add the following to your
package.json
:
{
"scripts": {
"postinstall": "patch-package --patch-dir node_modules/remix-three/patches"
}
}
- Use
useRemixBridge()
when you create your<Canvas>
:
// app/routes/canvas.tsx
import { useRemixBridge } from "remix-three";
export default function CanvasRoute() {
let RemixBridge = useRemixBridge();
return (
<Canvas>
<RemixBridge>
<MyScene />
</RemixBridge>
</Canvas>
);
}
function MyScene() {
let matches = useMatches();
let data = useLoaderData();
let location = useLocation();
return (
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshNormalMaterial />
</mesh>
);
}
NB: You must split out your scene content into a separate component that you render inside the RemixBridge in order to access anything from the remix or react-router context.
In general, this component takes the exact same props as a regular Remix <Link>
but wraps an Object3D
inside your scene. It works by invoking navigation directly in the same way a regular <Link>
would. It is totally possible this component may mess with your refs or click handlers of the child element, but I've done my best to avoid that.
import { Link3d } from 'remix-three'
function MyScene() {
return (
<Link to="./author">
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshNormalMaterial />
</mesh>
</Link>
<Outlet />
)
}