在 ThreeJS 中无法访问 RecoilJS RecoilRoot Canvas
RecoilJS RecoilRoot not accessible within ThreeJS Canvas
希望有人能帮助我。
我对 RecoilJS 很陌生,所以如果我遗漏了一些明显的东西,请告诉我。
我正在尝试使用 RecoilJS Atoms 管理场景中 3D 对象的状态。
我有一个鼠标悬停在最后一项的原子,我想显示一个调试面板及其信息。
出于某种原因,似乎无法从 ThreeJS canvas.
中访问 RecoilRoot 提供程序
在查看器(下面的代码)中,当我尝试声明 const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
(下面的完整跟踪)
时,我收到一条错误警告 This component must be used inside a <RecoilRoot> component
但是,从父级(查看器)向下传递 setHoveredLEDAtom
是可行的。
在 Debug 中声明它也可以,它是 Canvas 共享相同上下文的兄弟
目前这很好,但转向 Recoil 的全部意义在于停止上下传递道具。
我是否遗漏了一些明显的东西,或者 ThreeJS canvas 是否以某种方式存在于不同的范围内。
任何指点将不胜感激。
index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
// <React.StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
// </React.StrictMode>
App.js
function App() {
return (
<div className="App">
<Viewer />
</div>
);
}
观看者
const LED = ({ led }) => {
const [hovered, setHoevered] = useState(false);
const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
const handleHoverEnter = () => {
setHoveredLEDAtom(led);
setHoevered(true);
};
const handleHoverExit = () => {
setHoevered(false);
};
return (
<mesh
onPointerOver={(event) => handleHoverEnter()}
onPointerOut={(event) => handleHoverExit()}
>
<coneGeometry />
<meshStandardMaterial
color={hovered || led.brightness > 125 ? "hotpink" : "grey"}
/>
</mesh>
);
};
const Debug = () => {
const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
return (
<>
<div style={{ position: "absolute", left: "10px", top: "1rem" }}>
member : {hoveredLED.member}
</div>
</>
);
};
const Viewer = () => {
const [model, setModel] = useRecoilState(modelAtom);
const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
useEffect(() => {
console.log(hoveredLED);
}, [hoveredLED]);
return (
<>
<Debug />
<Canvas camera={{ position: [5, 7, 5] }} style={{ height: "700px" }}>
<Helpers />
<OrbitControls />
{model.map((led, index) => {
const key = `led-${index}`;
return (
<LED key={key} led={led} />
);
})}
</Canvas>
</>
);
};
export default Viewer;
错误
995 react-reconciler.development.js:9747 The above error occurred in the <LED> component:
at LED (http://localhost:3000/static/js/bundle.js:205:5)
at Suspense
at ErrorBoundary (http://localhost:3000/static/js/bundle.js:1998:5)
at Provider (http://localhost:3000/static/js/bundle.js:3860:5)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
logCapturedError @ react-reconciler.development.js:9747
2 react-three-fiber.esm.js:141 Uncaught Error: This component must be used inside a <RecoilRoot> component.
at err (recoil.js:16:1)
at Object.notInAContext (recoil.js:4092:1)
at updateRetainCount (recoil.js:3255:1)
at useRetain_ACTUAL (recoil.js:4669:1)
at useRetain (recoil.js:4627:1)
at useRecoilValueLoadable (recoil.js:5234:1)
at useRecoilValue (recoil.js:5258:1)
at useRecoilState (recoil.js:5306:1)
at LED (Viewer.js:76:1)
at renderWithHooks (react-reconciler.development.js:7363:1)
react-dom.development.js:18525 The above error occurred in the <ForwardRef(Canvas)> component:
at Canvas (http://localhost:3000/static/js/bundle.js:4179:5)
at Viewer (http://localhost:3000/static/js/bundle.js:325:83)
at div
at App
at RecoilRoot_INTERNAL (http://localhost:3000/static/js/bundle.js:91093:5)
at RecoilRoot (http://localhost:3000/static/js/bundle.js:91259:5)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
logCapturedError @ react-dom.development.js:18525
react-dom.development.js:26740 Uncaught Error: This component must be used inside a <RecoilRoot> component.
at err (recoil.js:16:1)
at Object.notInAContext (recoil.js:4092:1)
at updateRetainCount (recoil.js:3255:1)
at useRetain_ACTUAL (recoil.js:4669:1)
at useRetain (recoil.js:4627:1)
at useRecoilValueLoadable (recoil.js:5234:1)
at useRecoilValue (recoil.js:5258:1)
at useRecoilState (recoil.js:5306:1)
at LED (Viewer.js:76:1)
at renderWithHooks (react-reconciler.development.js:7363:1)
three.module.js:26599 THREE.WebGLRenderer: Context Lost.
来自 :
https://recoiljs.org/docs/api-reference/core/useRecoilBridgeAcrossReactRoots/
If a nested React root is created with ReactDOM.render(), or a nested
custom renderer is used, React will not propagate context state to the
child root. This hook is useful if you would like to "bridge" and
share Recoil state with a nested React root. The hook returns a React
component which you can use instead of in your nested
React root to share the same consistent Recoil store state. As with
any state sharing across React roots, changes may not be perfectly
synchronized in all cases.
所以桥接上下文很简单,只需创建一个桥并将其嵌套在 ThreeJS 中 Canvas
const Viewer = () => {
const RecoilBridge = useRecoilBridgeAcrossReactRoots_UNSTABLE();
...
return (
<>
<Canvas>
<RecoilBridge>
...
</RecoilBridge>
</Canvas>
</>
);
};
export default Viewer;
希望有人能帮助我。 我对 RecoilJS 很陌生,所以如果我遗漏了一些明显的东西,请告诉我。
我正在尝试使用 RecoilJS Atoms 管理场景中 3D 对象的状态。 我有一个鼠标悬停在最后一项的原子,我想显示一个调试面板及其信息。 出于某种原因,似乎无法从 ThreeJS canvas.
中访问 RecoilRoot 提供程序在查看器(下面的代码)中,当我尝试声明 const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
(下面的完整跟踪)
This component must be used inside a <RecoilRoot> component
但是,从父级(查看器)向下传递 setHoveredLEDAtom
是可行的。
在 Debug 中声明它也可以,它是 Canvas 共享相同上下文的兄弟
目前这很好,但转向 Recoil 的全部意义在于停止上下传递道具。
我是否遗漏了一些明显的东西,或者 ThreeJS canvas 是否以某种方式存在于不同的范围内。
任何指点将不胜感激。
index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
// <React.StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
// </React.StrictMode>
App.js
function App() {
return (
<div className="App">
<Viewer />
</div>
);
}
观看者
const LED = ({ led }) => {
const [hovered, setHoevered] = useState(false);
const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
const handleHoverEnter = () => {
setHoveredLEDAtom(led);
setHoevered(true);
};
const handleHoverExit = () => {
setHoevered(false);
};
return (
<mesh
onPointerOver={(event) => handleHoverEnter()}
onPointerOut={(event) => handleHoverExit()}
>
<coneGeometry />
<meshStandardMaterial
color={hovered || led.brightness > 125 ? "hotpink" : "grey"}
/>
</mesh>
);
};
const Debug = () => {
const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
return (
<>
<div style={{ position: "absolute", left: "10px", top: "1rem" }}>
member : {hoveredLED.member}
</div>
</>
);
};
const Viewer = () => {
const [model, setModel] = useRecoilState(modelAtom);
const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
useEffect(() => {
console.log(hoveredLED);
}, [hoveredLED]);
return (
<>
<Debug />
<Canvas camera={{ position: [5, 7, 5] }} style={{ height: "700px" }}>
<Helpers />
<OrbitControls />
{model.map((led, index) => {
const key = `led-${index}`;
return (
<LED key={key} led={led} />
);
})}
</Canvas>
</>
);
};
export default Viewer;
错误
995 react-reconciler.development.js:9747 The above error occurred in the <LED> component:
at LED (http://localhost:3000/static/js/bundle.js:205:5)
at Suspense
at ErrorBoundary (http://localhost:3000/static/js/bundle.js:1998:5)
at Provider (http://localhost:3000/static/js/bundle.js:3860:5)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
logCapturedError @ react-reconciler.development.js:9747
2 react-three-fiber.esm.js:141 Uncaught Error: This component must be used inside a <RecoilRoot> component.
at err (recoil.js:16:1)
at Object.notInAContext (recoil.js:4092:1)
at updateRetainCount (recoil.js:3255:1)
at useRetain_ACTUAL (recoil.js:4669:1)
at useRetain (recoil.js:4627:1)
at useRecoilValueLoadable (recoil.js:5234:1)
at useRecoilValue (recoil.js:5258:1)
at useRecoilState (recoil.js:5306:1)
at LED (Viewer.js:76:1)
at renderWithHooks (react-reconciler.development.js:7363:1)
react-dom.development.js:18525 The above error occurred in the <ForwardRef(Canvas)> component:
at Canvas (http://localhost:3000/static/js/bundle.js:4179:5)
at Viewer (http://localhost:3000/static/js/bundle.js:325:83)
at div
at App
at RecoilRoot_INTERNAL (http://localhost:3000/static/js/bundle.js:91093:5)
at RecoilRoot (http://localhost:3000/static/js/bundle.js:91259:5)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
logCapturedError @ react-dom.development.js:18525
react-dom.development.js:26740 Uncaught Error: This component must be used inside a <RecoilRoot> component.
at err (recoil.js:16:1)
at Object.notInAContext (recoil.js:4092:1)
at updateRetainCount (recoil.js:3255:1)
at useRetain_ACTUAL (recoil.js:4669:1)
at useRetain (recoil.js:4627:1)
at useRecoilValueLoadable (recoil.js:5234:1)
at useRecoilValue (recoil.js:5258:1)
at useRecoilState (recoil.js:5306:1)
at LED (Viewer.js:76:1)
at renderWithHooks (react-reconciler.development.js:7363:1)
three.module.js:26599 THREE.WebGLRenderer: Context Lost.
来自 : https://recoiljs.org/docs/api-reference/core/useRecoilBridgeAcrossReactRoots/
If a nested React root is created with ReactDOM.render(), or a nested custom renderer is used, React will not propagate context state to the child root. This hook is useful if you would like to "bridge" and share Recoil state with a nested React root. The hook returns a React component which you can use instead of in your nested React root to share the same consistent Recoil store state. As with any state sharing across React roots, changes may not be perfectly synchronized in all cases.
所以桥接上下文很简单,只需创建一个桥并将其嵌套在 ThreeJS 中 Canvas
const Viewer = () => {
const RecoilBridge = useRecoilBridgeAcrossReactRoots_UNSTABLE();
...
return (
<>
<Canvas>
<RecoilBridge>
...
</RecoilBridge>
</Canvas>
</>
);
};
export default Viewer;