Skip to content

Commit

Permalink
feat!: upgrade reconciler, react 18 concurrency (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyJasonBennett authored Aug 24, 2022
1 parent 32a74f8 commit c654781
Show file tree
Hide file tree
Showing 17 changed files with 7,612 additions and 26,952 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,13 @@ In addition to `createRoot` (see [custom canvas](#custom-canvas)), react-ogl exp
```tsx
import * as React from 'react'
import * as OGL from 'ogl'
import { type RootState, createRoot, reconciler } from 'react-ogl'
import { type RootState, createRoot, act } from 'react-ogl'

it('tests against a react-ogl component or scene', async () => {
const transform = React.createRef<OGL.Transform>()
let state: RootState = null!

await reconciler.act(async () => {
await act(async () => {
const root = createRoot(document.createElement('canvas'))
state = root.render(<transform ref={transform} />).getState()
})
Expand Down
4 changes: 2 additions & 2 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</head>
<body>
<script type="module">
import { render } from 'react-dom'
import { createRoot } from 'react-dom/client'

const demos = import.meta.glob('./src/*.tsx')

Expand Down Expand Up @@ -75,7 +75,7 @@
const root = entry.target.querySelector('div')
const loadDemo = demos[root.getAttribute('data-key')]

render((await loadDemo()).default, root)
createRoot(root).render((await loadDemo()).default)

entry.target.removeAttribute('data-key')
observer.unobserve(entry.target)
Expand Down
51 changes: 25 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,50 +26,49 @@
],
"devDependencies": {
"@swc/cli": "^0.1.57",
"@swc/core": "^1.2.213",
"@swc/jest": "^0.2.21",
"@testing-library/react": "^12.1.5",
"@testing-library/react-native": "^10.1.1",
"@types/jest": "^28.1.5",
"@types/react": "^17.0.47",
"@types/react-dom": "^17.0.17",
"@types/react-native": "^0.66.20",
"@typescript-eslint/eslint-plugin": "^5.30.6",
"@typescript-eslint/parser": "^5.30.6",
"@vitejs/plugin-react": "^2.0.0",
"eslint": "^8.19.0",
"@swc/core": "^1.2.242",
"@swc/jest": "^0.2.22",
"@testing-library/react": "^13.3.0",
"@types/jest": "^28.1.8",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@types/react-native": "^0.69.5",
"@typescript-eslint/eslint-plugin": "^5.34.0",
"@typescript-eslint/parser": "^5.34.0",
"@vitejs/plugin-react": "^2.0.1",
"eslint": "^8.22.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"expo-gl": "^11.1.1",
"expo-gl": "~11.4.0",
"jest": "^28.1.3",
"jest-environment-jsdom": "^28.1.3",
"ogl": "^0.0.97",
"prettier": "^2.7.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-native": "^0.67.1",
"react-test-renderer": "^17.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-native": "^0.69.4",
"react-test-renderer": "^18.2.0",
"rimraf": "^3.0.2",
"typescript": "^4.7.4",
"vite": "^3.0.0"
"vite": "^3.0.9"
},
"dependencies": {
"@expo/browser-polyfill": "^1.0.0",
"@types/ogl": "npm:ogl-types@^0.0.97",
"@types/react-reconciler": "^0.26.4",
"@types/webxr": "^0.4.0",
"react-reconciler": "^0.26.2",
"@types/react-reconciler": "^0.26.7",
"@types/webxr": "^0.5.0",
"react-reconciler": "^0.27.0",
"react-use-measure": "^2.1.1",
"suspend-react": "^0.0.8",
"zustand": "3.7.1"
"zustand": "^4.1.1"
},
"peerDependencies": {
"expo-gl": ">=11.0",
"expo-gl": ">=11.4",
"ogl": ">=0.0.97",
"react": ">=17.0",
"react-dom": ">=17.0",
"react-native": ">=0.64"
"react": ">=18.0",
"react-dom": ">=18.0",
"react-native": ">=0.69"
},
"peerDependenciesMeta": {
"react-dom": {
Expand Down
3 changes: 1 addition & 2 deletions src/Canvas.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface CanvasProps extends Omit<RenderProps, 'size' | 'dpr'>, ViewProp
* A resizeable canvas whose children are declarative OGL elements.
*/
export const Canvas = React.forwardRef<View, CanvasProps>(function Canvas(
{ children, style, mode, renderer, camera, orthographic, frameloop, events = createTouchEvents, onCreated, ...props },
{ children, style, renderer, camera, orthographic, frameloop, events = createTouchEvents, onCreated, ...props },
forwardedRef,
) {
const [{ width, height }, setSize] = React.useState({ width: 0, height: 0 })
Expand Down Expand Up @@ -59,7 +59,6 @@ export const Canvas = React.forwardRef<View, CanvasProps>(function Canvas(
canvas,
{
size: { width, height },
mode,
orthographic,
frameloop,
renderer,
Expand Down
2 changes: 0 additions & 2 deletions src/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export const Canvas = React.forwardRef<HTMLCanvasElement, CanvasProps>(function
resize,
children,
style,
mode,
renderer,
dpr,
camera,
Expand Down Expand Up @@ -57,7 +56,6 @@ export const Canvas = React.forwardRef<HTMLCanvasElement, CanvasProps>(function
canvas,
{
size: { width, height },
mode,
orthographic,
frameloop,
renderer,
Expand Down
9 changes: 0 additions & 9 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ export const POINTER_EVENTS = [
'onPointerOut',
] as const

/**
* React rendering modes (defaults to blocking).
*/
export const RENDER_MODES = {
legacy: 0,
blocking: 1,
concurrent: 2,
} as const

/**
* React internal props.
*/
Expand Down
11 changes: 9 additions & 2 deletions src/reconciler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Reconciler from 'react-reconciler'
import { DefaultEventPriority } from 'react-reconciler/constants'
import * as OGL from 'ogl'
import * as React from 'react'
import { toPascalCase, applyProps, attach, detach, classExtends } from './utils'
import { RESERVED_PROPS } from './constants'
import { Catalogue, Fiber, Instance, InstanceProps, OGLElements } from './types'
import { Act, Catalogue, Fiber, Instance, InstanceProps, OGLElements } from './types'

// Custom objects that extend the OGL namespace
const catalogue = { ...OGL } as unknown as Catalogue
Expand Down Expand Up @@ -291,7 +292,6 @@ export const reconciler = Reconciler<
scheduleTimeout: () => (typeof setTimeout !== 'undefined' ? setTimeout : undefined),
cancelTimeout: () => (typeof clearTimeout !== 'undefined' ? clearTimeout : undefined),
noTimeout: -1,
now: typeof performance !== 'undefined' ? performance.now : Date.now,
// Text isn't supported so we skip it
shouldSetTextContent: () => false,
resetTextContent: () => {},
Expand Down Expand Up @@ -397,8 +397,15 @@ export const reconciler = Reconciler<
// about side-effects if react changes its mind and discards an instance (e.g. React.Suspense)
finalizeInitialChildren: () => true,
commitMount: commitInstance,
// @ts-ignore
getCurrentEventPriority: () => DefaultEventPriority,
beforeActiveInstanceBlur: () => {},
afterActiveInstanceBlur: () => {},
detachDeletedInstance: () => {},
})

export const act: Act = (React as any).unstable_act

// Inject renderer meta into devtools
const isProd = typeof process === 'undefined' || process.env?.['NODE_ENV'] === 'production'
reconciler.injectIntoDevTools({
Expand Down
17 changes: 14 additions & 3 deletions src/renderer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as OGL from 'ogl'
import * as React from 'react'
import { ReactPortal } from 'react-reconciler'
import { ConcurrentRoot } from 'react-reconciler/constants'
import create, { GetState, SetState } from 'zustand'
import { reconciler } from './reconciler'
import { RENDER_MODES } from './constants'
import { OGLContext, useStore } from './hooks'
import { Fiber, Instance, InstanceProps, RenderProps, Root, RootState, RootStore, Subscription } from './types'
import { applyProps, calculateDpr } from './utils'
Expand All @@ -18,7 +18,6 @@ export function render(
element: React.ReactNode,
target: HTMLCanvasElement,
{
mode = 'blocking',
dpr = [1, 2],
size = { width: target.parentElement?.clientWidth ?? 0, height: target.parentElement?.clientHeight ?? 0 },
frameloop = 'always',
Expand Down Expand Up @@ -152,8 +151,20 @@ export function render(
store.subscribe(onResize)
onResize(state)

// Report when an error was detected in a previous render
const logRecoverableError = typeof reportError === 'function' ? reportError : console.error

// Create root container
const container = reconciler.createContainer(store as Fiber, RENDER_MODES[mode], false, null)
const container = reconciler.createContainer(
store as Fiber,
ConcurrentRoot,
null,
false,
null,
'',
logRecoverableError,
null,
)

// Set root
root = { container, store }
Expand Down
6 changes: 3 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { Fiber as ReconcilerFiber } from 'react-reconciler'
import type * as OGL from 'ogl'
import type * as React from 'react'
import type { SetState, GetState, UseBoundStore, StoreApi } from 'zustand'
import type { RENDER_MODES } from './constants'

export interface OGLEvent<TEvent extends Event> extends Partial<OGL.RaycastHit> {
nativeEvent: TEvent
Expand Down Expand Up @@ -102,7 +101,9 @@ export interface RootState {
[key: string]: any
}

export type RootStore = UseBoundStore<RootState, StoreApi<RootState>>
export type Act = (cb: () => Promise<any>) => Promise<any>

export type RootStore = UseBoundStore<StoreApi<RootState>>

export interface Root {
render: (element: React.ReactNode) => RootStore
Expand All @@ -126,7 +127,6 @@ export type RenderProps = {
scene?: OGL.Transform
events?: EventManager
onCreated?: (state: RootState) => any
mode?: keyof typeof RENDER_MODES
}

type NonFunctionKeys<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]
Expand Down
Loading

0 comments on commit c654781

Please sign in to comment.