Skip to content

Commit

Permalink
feat: upgrade reconciler for React 19
Browse files Browse the repository at this point in the history
Signed-off-by: Trezy <[email protected]>
  • Loading branch information
trezy committed Dec 30, 2024
1 parent b40f654 commit 07cfdac
Show file tree
Hide file tree
Showing 79 changed files with 590 additions and 341 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ const MyComponent = () => {
If you're using Typescript, this new `<viewport>` component will throw type errors. Pixi React exports a `PixiReactElementProps` type that can be used to solve this. You'll need to pass the `Viewport` into `PixiReactElementProps` and inject it into JSX:

```ts
import type { PixiReactElementProps } from '@pixi/react'
import type { Viewport } from 'pixi-viewport'
import { type PixiReactElementProps } from '@pixi/react'
import { type Viewport } from 'pixi-viewport'

declare global {
namespace JSX {
Expand Down
40 changes: 20 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.1.0",
"@testing-library/user-event": "^14.5.2",
"@types/react": "^18.3.2",
"@types/react-reconciler": "0.28.8",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@types/react-reconciler": "^0.28.9",
"@vitejs/plugin-react": "^4.3.1",
"@vitest/browser": "^2.0.4",
"husky": "^8.0.0",
Expand Down
56 changes: 20 additions & 36 deletions src/components/Application.ts → src/components/Application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
import {
createElement,
forwardRef,
type ForwardRefRenderFunction,
type MutableRefObject,
type RefObject,
useCallback,
useEffect,
useImperativeHandle,
useRef,
} from 'react';
import { createRoot } from '../core/createRoot';
Expand All @@ -19,17 +19,16 @@ import { queueForUnmount } from '../helpers/queueForUnmount';
import { unqueueForUnmount } from '../helpers/unqueueForUnmount';
import { useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect';
import { type ApplicationProps } from '../typedefs/ApplicationProps';
import { type ApplicationRef } from '../typedefs/ApplicationRef';

const originalDefaultTextStyle = { ...TextStyle.defaultTextStyle };

/** Creates a React root and renders a Pixi application. */
export const ApplicationFunction: ForwardRefRenderFunction<PixiApplication, ApplicationProps> = (
export const Application = forwardRef<ApplicationRef, ApplicationProps>(function Application(
props,
forwardedRef,
) =>
)
{
const {
attachToDevTools,
children,
className,
defaultTextStyle,
Expand All @@ -39,9 +38,20 @@ export const ApplicationFunction: ForwardRefRenderFunction<PixiApplication, Appl
...applicationProps
} = props;

const applicationRef: MutableRefObject<PixiApplication | null> = useRef(null);
const canvasRef: MutableRefObject<HTMLCanvasElement | null> = useRef(null);
const extensionsRef: MutableRefObject<Set<any>> = useRef(new Set());
const applicationRef: RefObject<PixiApplication | null> = useRef(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const extensionsRef = useRef<Set<any>>(new Set());

useImperativeHandle(forwardedRef, () => ({
getApplication()
{
return applicationRef.current;
},
getCanvas()
{
return canvasRef.current;
},
}));

const updateResizeTo = useCallback(() =>
{
Expand Down Expand Up @@ -75,31 +85,9 @@ export const ApplicationFunction: ForwardRefRenderFunction<PixiApplication, Appl
{
processUnmountQueue();

if (forwardedRef && ('current' in forwardedRef))
{
forwardedRef.current = application;
}

applicationRef.current = application;
updateResizeTo();
onInit?.(application);

if (attachToDevTools)
{
const globalScope = globalThis as any;

globalScope.__PIXI_APP__ = application;

import('pixi.js').then((pixi) =>
{
globalScope.__PIXI_DEVTOOLS__ = {
app: application,
pixi,
renderer: application.renderer,
stage: application.stage,
};
});
}
}, [onInit]);

useIsomorphicLayoutEffect(() =>
Expand Down Expand Up @@ -193,8 +181,4 @@ export const ApplicationFunction: ForwardRefRenderFunction<PixiApplication, Appl
className,
ref: canvasRef,
});
};

ApplicationFunction.displayName = 'Application';

export const Application = forwardRef(ApplicationFunction);
});
3 changes: 1 addition & 2 deletions src/components/Context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createContext } from 'react';

import type { ApplicationState } from '../typedefs/ApplicationState';
import { type ApplicationState } from '../typedefs/ApplicationState';

export const Context = createContext<ApplicationState>({} as ApplicationState);

Expand Down
3 changes: 3 additions & 0 deletions src/constants/NO_CONTEXT.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { type HostConfig } from '../typedefs/HostConfig';

export const NO_CONTEXT: HostConfig['hostContext'] = {};
35 changes: 18 additions & 17 deletions src/core/createRoot.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { Application } from 'pixi.js';
import { type ApplicationOptions } from 'pixi.js';
import { createElement } from 'react';
import { type ReactNode } from 'react';
import { ConcurrentRoot } from 'react-reconciler/constants.js';
import { ContextProvider } from '../components/Context';
import { isReadOnlyProperty } from '../helpers/isReadOnlyProperty';
import { log } from '../helpers/log';
import { prepareInstance } from '../helpers/prepareInstance';
import { type ApplicationState } from '../typedefs/ApplicationState';
import { type CreateRootOptions } from '../typedefs/CreateRootOptions';
import { type HostConfig } from '../typedefs/HostConfig';
import { type InternalState } from '../typedefs/InternalState';
import { reconciler } from './reconciler';
import { roots } from './roots';

import type { ApplicationOptions } from 'pixi.js';
import type { ReactNode } from 'react';
import type { ApplicationState } from '../typedefs/ApplicationState';
import type { CreateRootOptions } from '../typedefs/CreateRootOptions';
import type { HostConfig } from '../typedefs/HostConfig';
import type { InternalState } from '../typedefs/InternalState';

/** Creates a new root for a Pixi React app. */
export function createRoot(
/** @description The DOM node which will serve as the root for this tree. */
Expand Down Expand Up @@ -49,15 +48,17 @@ export function createRoot(
internalState.rootContainer = prepareInstance(applicationState.app.stage) as HostConfig['containerInstance'];
}

const fiber = root?.fiber ?? reconciler.createContainer(
internalState.rootContainer,
ConcurrentRoot,
null,
false,
null,
'',
console.error,
null,
const fiber = root?.fiber ?? (reconciler as any).createContainer(
internalState.rootContainer, // container
ConcurrentRoot, // tag
null, // hydration callbacks
false, // isStrictMode
null, // concurrentUpdatesByDefaultOverride
'', // identifierPrefix
console.error, // onUncaughtError
console.error, // onCaughtError
console.error, // onRecoverableError
null, // transitionCallbacks
);

if (!root)
Expand Down Expand Up @@ -98,7 +99,7 @@ export function createRoot(

Object.entries(applicationOptions).forEach(([key, value]) =>
{
const typedKey = /** @type {keyof ApplicationOptions} */ (key);
const typedKey = key as keyof ApplicationOptions;

if (isReadOnlyProperty(
applicationOptions as unknown as Record<string, unknown>,
Expand Down
Loading

0 comments on commit 07cfdac

Please sign in to comment.