Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow configuring custom fiber, add missing createContainer arguments #534

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading