Skip to content

Commit

Permalink
#164 WIP - Error: "Expected host context to exist. This error is like…
Browse files Browse the repository at this point in the history
…ly caused by a bug in React. Please file an issue."
  • Loading branch information
brianzinn committed Oct 26, 2021
1 parent 4ad062e commit 50e342b
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 7 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@types/mocha": "^8.2.0",
"@types/node": "^14.14.10",
"@types/react": "^17.0.27",
"@types/react-reconciler": "^0.18.0",
"@types/react-reconciler": "^0.26.4",
"@types/sinon": "^9.0.10",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/parser": "^4.29.1",
Expand Down Expand Up @@ -79,6 +79,6 @@
"react-dom": ">=17"
},
"dependencies": {
"react-reconciler": "^0.26.1"
"react-reconciler": "^0.26.2"
}
}
6 changes: 4 additions & 2 deletions src/react-babylonjs.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
export * from './customComponents';
export * from './generatedCode';
export * from './generatedProps';
export * from './hooks';
export * from './customComponents';
export * from './PropsHandler';
export * from './HostRegistrationStore';
export * from './PropsHandler';
export * from './render';

// applyInitialPropsToInstance is marked deprecated
export { applyInitialPropsToInstance } from './plugins'; // Imported by react-babylonjs-spring

Expand Down
11 changes: 8 additions & 3 deletions src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@ export interface ReconcilerInstance {
unmount: (container: Container) => void;
}

const ReconcilerSecondary: ReconcilerType<any, any, Container, any> = Reconciler(ReactBabylonJSHostConfig);
const ReconcilerPrimary: ReconcilerType<any, any, Container, any> = Reconciler({ ...ReactBabylonJSHostConfig, isPrimaryRenderer: true });
const ReconcilerSecondary: ReconcilerType<Container, any, any, any, any> = Reconciler(ReactBabylonJSHostConfig);
const ReconcilerPrimary: ReconcilerType<Container, any, any, any, any> = Reconciler({ ...ReactBabylonJSHostConfig, isPrimaryRenderer: true });

export function createPortal(children: React.ReactNode, containerInfo: any, key?: string | null, usePrimary: boolean = false): Reconciler.ReactPortal {
const reconciler = (usePrimary === true ? ReconcilerPrimary : ReconcilerSecondary);
return reconciler.createPortal(children, containerInfo, null, key);
}

/*
* Creates a reconciler instance using an internal pre-existing Reconciler instance.
* So far the only option is if you want a primary renderer (non-default).
*/
export function createReconciler(rendererOptions: RendererOptions): ReconcilerInstance {

const reconciler: ReconcilerType<any, any, Container, any> = (rendererOptions.usePrimary === true)
const reconciler: ReconcilerType<Container, any, any, any, any> = (rendererOptions.usePrimary === true)
? ReconcilerPrimary
: ReconcilerSecondary;

Expand Down
51 changes: 51 additions & 0 deletions storybook/stories/babylonjs/Basic/portal.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useEffect, useRef, useState } from 'react';
import '@babylonjs/inspector';
import { Engine, Scene, useBeforeRender, createPortal } from '../../../../dist/react-babylonjs';
import { Vector3 } from '@babylonjs/core/Maths/math'
import '../../style.css'

export default { title: 'Babylon Basic' };

const rpm = 5;

function WithCreatePortal() {
const transformNodeRef = useRef(null);
const [_, setReady] = useState(false);

useBeforeRender((scene) => {
if (transformNodeRef.current !== null) {
const deltaTimeInMillis = scene.getEngine().getDeltaTime();
transformNodeRef.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000));
}
})

useEffect(() => {
console.log('trigger re-render when transform node is set.');
setReady(true);
}, [transformNodeRef.current])

return (
<>
<transformNode name="transform-node" ref={transformNodeRef}>
{(transformNodeRef.current) &&
createPortal(<box position={new Vector3(0, 1, 0)} />, transformNodeRef.current)
}
<ground name='ground1' width={6} height={6} subdivisions={2} position={new Vector3(0, 0, 0)} />
</transformNode>
</>
)
}

export const CreatePortal = () => (
<div style={{ flex: 1, display: 'flex' }}>
<Engine antialias adaptToDeviceRatio canvasId='babylonJS'>
<Scene>
<freeCamera name='camera1' position={new Vector3(0, 5, -10)}
setTarget={[Vector3.Zero()]} />

<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
<WithCreatePortal />
</Scene>
</Engine>
</div>
)

0 comments on commit 50e342b

Please sign in to comment.