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

fix(types): add shell types for react-reconciler changes #3242

Merged
merged 3 commits into from
May 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
114 changes: 106 additions & 8 deletions packages/fiber/src/core/reconciler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as THREE from 'three'
import * as React from 'react'
import Reconciler from 'react-reconciler'
import {
// @ts-expect-error
NoEventPriority,
ContinuousEventPriority,
DiscreteEventPriority,
Expand All @@ -23,6 +22,103 @@ import type { RootStore } from './store'
import { removeInteractivity, type EventHandlers } from './events'
import type { ThreeElement } from '../three-types'

// TODO: upstream to DefinitelyTyped for React 19
// https://github.com/facebook/react/issues/28956
type EventPriority = number

const createReconciler = Reconciler as unknown as <
Type,
Props,
Container,
Instance,
TextInstance,
SuspenseInstance,
HydratableInstance,
FormInstance,
PublicInstance,
HostContext,
ChildSet,
TimeoutHandle,
NoTimeout,
TransitionStatus,
>(
config: Omit<
Reconciler.HostConfig<
Type,
Props,
Container,
Instance,
TextInstance,
SuspenseInstance,
HydratableInstance,
PublicInstance,
HostContext,
null, // updatePayload
ChildSet,
TimeoutHandle,
NoTimeout
>,
'getCurrentEventPriority' | 'prepareUpdate' | 'commitUpdate'
> & {
/**
* This method should mutate the `instance` and perform prop diffing if needed.
*
* The `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its internal fields, be aware that it may change significantly between versions. You're taking on additional maintenance risk by reading from it, and giving up all guarantees if you write something to it.
*/
commitUpdate?(
instance: Instance,
type: Type,
prevProps: Props,
nextProps: Props,
internalHandle: Reconciler.OpaqueHandle,
): void

// Undocumented
// https://github.com/facebook/react/pull/26722
NotPendingTransition: TransitionStatus | null
// https://github.com/facebook/react/pull/28751
setCurrentUpdatePriority(newPriority: EventPriority): void
getCurrentUpdatePriority(): EventPriority
resolveUpdatePriority(): EventPriority
// https://github.com/facebook/react/pull/28804
resetFormInstance(form: FormInstance): void
// https://github.com/facebook/react/pull/25105
requestPostPaintCallback(callback: (time: number) => void): void
// https://github.com/facebook/react/pull/26025
shouldAttemptEagerTransition(): boolean

/**
* This method is called during render to determine if the Host Component type and props require some kind of loading process to complete before committing an update.
*/
maySuspendCommit(type: Type, props: Props): boolean
/**
* This method may be called during render if the Host Component type and props might suspend a commit. It can be used to initiate any work that might shorten the duration of a suspended commit.
*/
preloadInstance(type: Type, props: Props): boolean
/**
* This method is called just before the commit phase. Use it to set up any necessary state while any Host Components that might suspend this commit are evaluated to determine if the commit must be suspended.
*/
startSuspendingCommit(): void
/**
* This method is called after `startSuspendingCommit` for each Host Component that indicated it might suspend a commit.
*/
suspendInstance(type: Type, props: Props): void
/**
* This method is called after all `suspendInstance` calls are complete.
*
* Return `null` if the commit can happen immediately.
*
* Return `(initiateCommit: Function) => Function` if the commit must be suspended. The argument to this callback will initiate the commit when called. The return value is a cancellation function that the Reconciler can use to abort the commit.
*
*/
waitForCommitToBeReady(): ((initiateCommit: Function) => Function) | null
},
) => Reconciler.Reconciler<Container, Instance, TextInstance, SuspenseInstance, PublicInstance>

declare module 'react-reconciler/constants' {
const NoEventPriority = 0
}

export interface Root {
fiber: Reconciler.FiberRoot
store: RootStore
Expand Down Expand Up @@ -76,12 +172,13 @@ interface HostConfig {
textInstance: void
suspenseInstance: Instance
hydratableInstance: never
formInstance: never
publicInstance: Instance['object']
hostContext: {}
updatePayload: null | [true] | [false, Instance['props']] // NOTE: removed with React 19
childSet: never
timeoutHandle: number | undefined
noTimeout: -1
TransitionStatus: null
}

export const catalogue: Catalogue = {}
Expand Down Expand Up @@ -324,20 +421,21 @@ const NO_CONTEXT: HostConfig['hostContext'] = {}

let currentUpdatePriority: number = NoEventPriority

export const reconciler = Reconciler<
export const reconciler = createReconciler<
HostConfig['type'],
HostConfig['props'],
HostConfig['container'],
HostConfig['instance'],
HostConfig['textInstance'],
HostConfig['suspenseInstance'],
HostConfig['hydratableInstance'],
HostConfig['formInstance'],
HostConfig['publicInstance'],
HostConfig['hostContext'],
HostConfig['updatePayload'],
HostConfig['childSet'],
HostConfig['timeoutHandle'],
HostConfig['noTimeout']
HostConfig['noTimeout'],
HostConfig['TransitionStatus']
>({
isPrimaryRenderer: false,
warnsIfNotActing: false,
Expand Down Expand Up @@ -369,7 +467,6 @@ export const reconciler = Reconciler<
},
getRootHostContext: () => NO_CONTEXT,
getChildHostContext: () => NO_CONTEXT,
// @ts-expect-error prepareUpdate and updatePayload removed with React 19
commitUpdate(
instance: HostConfig['instance'],
type: HostConfig['type'],
Expand Down Expand Up @@ -418,8 +515,8 @@ export const reconciler = Reconciler<
beforeActiveInstanceBlur() {},
afterActiveInstanceBlur() {},
detachDeletedInstance() {},
// TODO: add shell types for these and upstream to DefinitelyTyped
// https://github.com/facebook/react/blob/main/packages/react-art/src/ReactFiberConfigART.js
prepareScopeUpdate() {},
getInstanceFromScope: () => null,
shouldAttemptEagerTransition() {
return false
},
Expand Down Expand Up @@ -464,4 +561,5 @@ export const reconciler = Reconciler<
return DefaultEventPriority
}
},
resetFormInstance() {},
})