Skip to content

Commit

Permalink
allow configuring custom fiber, add missing arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
laino committed Aug 31, 2024
1 parent 843be67 commit 28888a3
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 23 deletions.
22 changes: 17 additions & 5 deletions packages/react/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ interface ReconcilerConfig
mountEventComponent(): void;
updateEventComponent(): void;
handleEventTarget(): void;
noTimeout: any;
scheduleTimeout(...args: any[]): any;
cancelTimeout(...args: any[]): any;
supportsMicrotasks: boolean,
scheduleMicrotask(...args: any[]): any,
appendChild(...args: any[]): any;
appendChildToContainer(...args: any[]): any;
removeChild(...args: any[]): any;
Expand Down Expand Up @@ -277,6 +280,11 @@ declare namespace _ReactPixi
*/
raf?: boolean;

/**
* Use a custom reconciler.
*/
fiber?: Reconciler<any, any, any, any>;

/**
* Render the PIXI stage on React component changes.
* You'll need to set raf={false}.
Expand Down Expand Up @@ -391,7 +399,7 @@ export interface ReactPixiRoot {
unmount(): void
}

export const createRoot: (container: PixiContainer) => ReactPixiRoot
export const createRoot: (container: PixiContainer, fiber?: Reconciler<any, any, any, any>) => ReactPixiRoot

// renderer
export const render: (
Expand All @@ -401,17 +409,21 @@ export const render: (
) => any;

// unmount component
export const unmountComponentAtNode: (container: PixiContainer) => void;
export const unmountComponentAtNode: (container: PixiContainer, fiber?: Reconciler<any, any, any, any>) => void;

// context
export const AppContext: React.Context<PixiApplication>;
export const AppProvider: React.ComponentType<React.ProviderProps<PixiApplication>>;
export const AppConsumer: React.ComponentType<React.ConsumerProps<PixiApplication>>;

// fiber
export const PixiFiber: (
eventsMap?: { [P in keyof ReconcilerConfig]: (...args: any) => void }
) => Reconciler<any, any, any, any>;
export const PixiFiber: Reconciler<any, any, any, any>;

// re-exported reconciler from react
export const Reconciler: (config: ReconcilerConfig) => Reconciler<any, any, any, any>;

// default hostconfig
export const hostconfig: ReconcilerConfig;

// stage
export class Stage extends React.Component<_ReactPixi.IStage> {}
Expand Down
4 changes: 3 additions & 1 deletion packages/react/src/exports.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PixiComponent, TYPES } from './utils/element';
import { createRoot, render, unmountComponentAtNode } from './render';
import Stage from './stage';
import { PixiFiber } from './reconciler';
import { PixiFiber, Reconciler, hostconfig } from './reconciler';
import { Context as AppContext, AppProvider, AppConsumer, withPixiApp } from './stage/provider';
import { useTick, useApp } from './hooks';
import { withFilters } from './hoc';
Expand All @@ -22,6 +22,8 @@ export {
withPixiApp,
PixiComponent,
PixiFiber,
hostconfig,
Reconciler,
AppProvider,
AppConsumer,
AppContext,
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/reconciler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Reconciler from 'react-reconciler';
import pkg from '../../../../package.json';
import hostconfig from './hostconfig';

export { hostconfig, Reconciler };
export const PixiFiber = Reconciler(hostconfig);

export const VERSION = pkg.version;
Expand Down
29 changes: 20 additions & 9 deletions packages/react/src/render/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Container } from '@pixi/display';
import invariant from '../utils/invariant';
import { PixiFiber } from '../reconciler';
import { Reconciler } from 'react-reconciler';

// cache both root PixiFiber containers and React roots
export const roots = new Map();

/**
* @param {Container} container
*/
function unmountComponent(container)
function unmountComponent(container, fiber = PixiFiber)
{
invariant(
Container.prototype.isPrototypeOf(container),
Expand All @@ -20,7 +21,7 @@ function unmountComponent(container)
const { pixiFiberContainer } = roots.get(container);

// unmount component
PixiFiber.updateContainer(null, pixiFiberContainer, undefined, () =>
fiber.updateContainer(null, pixiFiberContainer, undefined, () =>
{
roots.delete(container);
});
Expand All @@ -32,9 +33,10 @@ function unmountComponent(container)
* Use this without React-DOM
*
* @param {Container} container
* @param {Reconciler} custom fiber
* @returns {{ render: Function, unmount: Function}}
*/
export function createRoot(container)
export function createRoot(container, fiber = PixiFiber)
{
invariant(
Container.prototype.isPrototypeOf(container),
Expand All @@ -47,23 +49,32 @@ export function createRoot(container)

if (!root)
{
const pixiFiberContainer = PixiFiber.createContainer(container);
const pixiFiberContainer = fiber.createContainer(
container,
0,
null,
false,
null,
'',
(error) => console.error('React recoverable error:', error),
null
);

const reactRoot = {
render(element)
{
// schedules a top level update
PixiFiber.updateContainer(
fiber.updateContainer(
element,
pixiFiberContainer,
undefined
);

return PixiFiber.getPublicRootInstance(pixiFiberContainer);
return fiber.getPublicRootInstance(pixiFiberContainer);
},
unmount()
{
unmountComponent(container);
unmountComponent(container, fiber);
roots.delete(container);
},
};
Expand Down Expand Up @@ -116,7 +127,7 @@ export function render(element, container, callback)
* @deprecated use root.unmount() instead
* @param {Container} container
*/
export function unmountComponentAtNode(container)
export function unmountComponentAtNode(container, fiber)
{
unmountComponent(container);
unmountComponent(container, fiber);
}
27 changes: 23 additions & 4 deletions packages/react/src/stage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const propTypes = {

children: PropTypes.node,

fiber: PropTypes.any,

// PIXI options, see https://pixijs.download/v7.x/docs/PIXI.Application.html
options: PropTypes.shape({
autoStart: PropTypes.bool,
Expand Down Expand Up @@ -97,6 +99,7 @@ const defaultProps = {
onUnmount: noop,
raf: true,
renderOnComponentChange: true,
fiber: PixiFiber
};

export function getCanvasProps(props)
Expand All @@ -117,6 +120,7 @@ class Stage extends React.Component
_mediaQuery = null;
_ticker = null;
_needsUpdate = true;
_fiber = PixiFiber;
app = null;

componentDidMount()
Expand All @@ -128,8 +132,12 @@ class Stage extends React.Component
options,
raf,
renderOnComponentChange,
fiber,
} = this.props;

// We save the fiber from props because we can't support changing it
this._fiber = fiber;

this.app = new Application({
width,
height,
Expand All @@ -152,8 +160,19 @@ class Stage extends React.Component
this.app.ticker[raf ? 'start' : 'stop']();

this.app.stage.__reactpixi = { root: this.app.stage };
this.mountNode = PixiFiber.createContainer(this.app.stage);
PixiFiber.updateContainer(this.getChildren(), this.mountNode, this);

this.mountNode = this._fiber.createContainer(
this.app.stage,
0,
null,
false,
null,
'',
(error) => console.error('React recoverable error:', error),
null
);

this._fiber.updateContainer(this.getChildren(), this.mountNode, this);

onMount(this.app);

Expand Down Expand Up @@ -219,7 +238,7 @@ class Stage extends React.Component
}

// flush fiber
PixiFiber.updateContainer(this.getChildren(), this.mountNode, this);
this._fiber.updateContainer(this.getChildren(), this.mountNode, this);

if (
prevProps.width !== width
Expand Down Expand Up @@ -306,7 +325,7 @@ class Stage extends React.Component
this.needsRenderUpdate
);

PixiFiber.updateContainer(null, this.mountNode, this);
this._fiber.updateContainer(null, this.mountNode, this);

if (this._mediaQuery)
{
Expand Down
57 changes: 57 additions & 0 deletions packages/react/test/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ exports[`index export modules for index 1`] = `
"shouldSuspend": [Function],
"updateContainer": [Function],
},
"Reconciler": [Function],
"SimpleMesh": "SimpleMesh",
"SimpleRope": "SimpleRope",
"Sprite": "Sprite",
Expand Down Expand Up @@ -151,6 +152,62 @@ exports[`index export modules for index 1`] = `
"touchmove",
"touchstart",
],
"hostconfig": {
"afterActiveInstanceBlur": [Function],
"appendChild": [Function],
"appendChildToContainer": [Function],
"appendInitialChild": [Function],
"beforeActiveInstanceBlur": [Function],
"cancelTimeout": [Function],
"clearContainer": [Function],
"commitMount": [Function],
"commitTextUpdate": [Function],
"commitUpdate": [Function],
"createInstance": [Function],
"createTextInstance": [Function],
"detachDeletedInstance": [Function],
"finalizeInitialChildren": [Function],
"getChildHostContext": [Function],
"getChildHostContextForEventComponent": [Function],
"getCurrentEventPriority": [Function],
"getFundamentalComponentInstance": [Function],
"getInstanceFromNode": [Function],
"getPublicInstance": [Function],
"getRootHostContext": [Function],
"handleEventTarget": [Function],
"hideInstance": [Function],
"insertBefore": [Function],
"insertInContainerBefore": [Function],
"isOpaqueHydratingObject": [Function],
"isPrimaryRenderer": false,
"makeClientIdInDEV": [Function],
"makeOpaqueHydratingObject": [Function],
"mountEventComponent": [Function],
"mountFundamentalComponent": [Function],
"noTimeout": -1,
"now": [Function],
"prepareForCommit": [Function],
"preparePortalMount": [Function],
"prepareUpdate": [Function],
"removeChild": [Function],
"removeChildFromContainer": [Function],
"resetAfterCommit": [Function],
"resetTextContent": [Function],
"scheduleMicrotask": [Function],
"scheduleTimeout": [Function],
"shouldDeprioritizeSubtree": [Function],
"shouldSetTextContent": [Function],
"shouldUpdateFundamentalComponent": [Function],
"supportsHydration": false,
"supportsMicrotasks": true,
"supportsMutation": true,
"supportsPersistence": false,
"unhideInstance": [Function],
"unhideTextInstance": [Function],
"unmountFundamentalComponent": [Function],
"updateEventComponent": [Function],
"warnsIfNotActing": false,
},
"render": [Function],
"unmountComponentAtNode": [Function],
"useApp": [Function],
Expand Down
38 changes: 38 additions & 0 deletions packages/react/test/__snapshots__/stage.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
exports[`stage prop types 1`] = `
{
"children": [Function],
"fiber": [Function],
"height": [Function],
"onMount": [Function],
"onUnmount": [Function],
Expand All @@ -15,6 +16,43 @@ exports[`stage prop types 1`] = `

exports[`stage prop types 2`] = `
{
"fiber": {
"attemptContinuousHydration": [MockFunction],
"attemptDiscreteHydration": [MockFunction],
"attemptHydrationAtCurrentPriority": [MockFunction],
"attemptSynchronousHydration": [MockFunction],
"batchedUpdates": [MockFunction],
"createComponentSelector": [MockFunction],
"createContainer": [MockFunction],
"createHasPseudoClassSelector": [MockFunction],
"createHydrationContainer": [MockFunction],
"createPortal": [MockFunction],
"createRoleSelector": [MockFunction],
"createTestNameSelector": [MockFunction],
"createTextSelector": [MockFunction],
"deferredUpdates": [MockFunction],
"discreteUpdates": [MockFunction],
"findAllNodes": [MockFunction],
"findBoundingRects": [MockFunction],
"findHostInstance": [MockFunction],
"findHostInstanceWithNoPortals": [MockFunction],
"findHostInstanceWithWarning": [MockFunction],
"flushControlled": [MockFunction],
"flushPassiveEffects": [MockFunction],
"flushSync": [MockFunction],
"focusWithin": [MockFunction],
"getCurrentUpdatePriority": [MockFunction],
"getFindAllNodesFailureDescription": [MockFunction],
"getPublicRootInstance": [MockFunction],
"injectIntoDevTools": [MockFunction],
"isAlreadyRendering": [MockFunction],
"observeVisibleRects": [MockFunction],
"registerMutableSourceForHydration": [MockFunction],
"runWithPriority": [MockFunction],
"shouldError": [MockFunction],
"shouldSuspend": [MockFunction],
"updateContainer": [MockFunction],
},
"height": 600,
"onMount": [Function],
"onUnmount": [Function],
Expand Down
3 changes: 0 additions & 3 deletions packages/react/test/render.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ describe('render', () =>
{
renderElementToStage();
expect(PixiFiber.createContainer).toHaveBeenCalledTimes(1);
expect(PixiFiber.createContainer).toHaveBeenLastCalledWith(
app.stage,
);
});

test('call updateContainer', () =>
Expand Down
Loading

0 comments on commit 28888a3

Please sign in to comment.