首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RecoilJS RecoilRoot在ThreeJS画布中不可访问

RecoilJS RecoilRoot在ThreeJS画布中不可访问
EN

Stack Overflow用户
提问于 2022-04-25 10:27:06
回答 1查看 274关注 0票数 0

希望有人能帮我。我对RecoilJS很陌生,所以如果我遗漏了一些明显的东西,请告诉我。

我正在尝试用RecoilJS原子来管理场景中的3D对象的状态。我有一个原子的最后一个项目,鼠标盘旋在上面,我想显示一个调试面板及其信息。由于某些原因,RecoilRoot提供者似乎无法从ThreeJS画布中访问。

在查看器(下面的代码)中,当我试图声明This component must be used inside a <RecoilRoot> component时,会收到一个错误警告:const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom); (下面是完整的跟踪)

但是,从父(查看器)传递setHoveredLEDAtom是可行的。

在Debug中声明它也有效,这是一个共享相同上下文的画布兄弟。

就目前而言,这是好的,但整个后退的意义是停止通过道具上下。

我是遗漏了一些显而易见的东西,还是ThreeJS画布以某种方式存在于不同的范围内。

如有任何指示,将不胜感激。

index.js

代码语言:javascript
复制
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  // <React.StrictMode>
  <RecoilRoot>
    <App />
  </RecoilRoot>
  // </React.StrictMode>

App.js

代码语言:javascript
复制
function App() {
  return (
    <div className="App">
      <Viewer />
    </div>
  );
}

查看器

代码语言:javascript
复制
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>
  );
};
代码语言:javascript
复制
const Debug = () => {
  const [hoveredLED, setHoveredLEDAtom] = useRecoilState(hoveredLEDAtom);
  return (
    <>
      <div style={{ position: "absolute", left: "10px", top: "1rem" }}>
        member : {hoveredLED.member}
      </div>
    </>
  );
};
代码语言:javascript
复制
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;

错误

代码语言:javascript
复制
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.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-05 16:26:32

来自:https://recoiljs.org/docs/api-reference/core/useRecoilBridgeAcrossReactRoots/

如果使用ReactDOM.render()创建了嵌套的React根,或者使用了嵌套的自定义呈现器,那么React将不会将上下文状态传播到子根。如果您想要“桥接”并与嵌套的反作用根共享反冲状态,则此钩子非常有用。钩子返回一个React组件,您可以在嵌套的React中使用这个组件来共享相同的反冲存储状态。与任何跨React根的状态共享一样,更改可能并非在所有情况下都完全同步。

因此,连接上下文非常简单,比如创建一个桥并在ThreeJS画布中嵌套它。

代码语言:javascript
复制
const Viewer = () => {
  const RecoilBridge = useRecoilBridgeAcrossReactRoots_UNSTABLE();
  ...

  return (
    <>
      <Canvas>
        <RecoilBridge>
            ...
        </RecoilBridge>
      </Canvas>
    </>
  );
};

export default Viewer;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71998062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档