希望有人能帮我。我对RecoilJS很陌生,所以如果我遗漏了一些明显的东西,请告诉我。
我正在尝试用RecoilJS原子来管理场景中的3D对象的状态。我有一个原子的最后一个项目,鼠标盘旋在上面,我想显示一个调试面板及其信息。由于某些原因,RecoilRoot提供者似乎无法从ThreeJS画布中访问。
在查看器(下面的代码)中,当我试图声明This component must be used inside a <RecoilRoot> component时,会收到一个错误警告:const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom); (下面是完整的跟踪)
但是,从父(查看器)传递setHoveredLEDAtom是可行的。
在Debug中声明它也有效,这是一个共享相同上下文的画布兄弟。
就目前而言,这是好的,但整个后退的意义是停止通过道具上下。
我是遗漏了一些显而易见的东西,还是ThreeJS画布以某种方式存在于不同的范围内。
如有任何指示,将不胜感激。
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.发布于 2022-05-05 16:26:32
来自:https://recoiljs.org/docs/api-reference/core/useRecoilBridgeAcrossReactRoots/
如果使用ReactDOM.render()创建了嵌套的React根,或者使用了嵌套的自定义呈现器,那么React将不会将上下文状态传播到子根。如果您想要“桥接”并与嵌套的反作用根共享反冲状态,则此钩子非常有用。钩子返回一个React组件,您可以在嵌套的React中使用这个组件来共享相同的反冲存储状态。与任何跨React根的状态共享一样,更改可能并非在所有情况下都完全同步。
因此,连接上下文非常简单,比如创建一个桥并在ThreeJS画布中嵌套它。
const Viewer = () => {
const RecoilBridge = useRecoilBridgeAcrossReactRoots_UNSTABLE();
...
return (
<>
<Canvas>
<RecoilBridge>
...
</RecoilBridge>
</Canvas>
</>
);
};
export default Viewer;https://stackoverflow.com/questions/71998062
复制相似问题