Skip to content

Commit

Permalink
Merge pull request #3262 from pmndrs/fix/remove-use-update
Browse files Browse the repository at this point in the history
[v9] fix: remove `useUpdate`
  • Loading branch information
krispya committed May 22, 2024
2 parents 09637a2 + c49e02a commit 9ba7697
Show file tree
Hide file tree
Showing 11 changed files with 25 additions and 411 deletions.
121 changes: 0 additions & 121 deletions example/src/demos/Update.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions example/src/demos/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const Test = { Component: lazy(() => import('./Test')) }
const Viewcube = { Component: lazy(() => import('./Viewcube')) }
const Portals = { Component: lazy(() => import('./Portals')) }
const ViewTracking = { Component: lazy(() => import('./ViewTracking')) }
const Update = { Component: lazy(() => import('./Update')) }

export {
Animation,
Expand All @@ -51,5 +50,4 @@ export {
MultiView,
Portals,
ViewTracking,
Update,
}
18 changes: 1 addition & 17 deletions packages/fiber/src/core/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as THREE from 'three'
import * as React from 'react'
import { suspend, preload, clear } from 'suspend-react'
import { context, RootState, RenderCallback, UpdateCallback, StageTypes, RootStore } from './store'
import { context, RootState, RenderCallback, RootStore } from './store'
import { buildGraph, ObjectMap, is, useMutableCallback, useIsomorphicLayoutEffect, isObject3D } from './utils'
import { Stages } from './stages'
import type { Instance } from './reconciler'

/**
Expand Down Expand Up @@ -54,21 +53,6 @@ export function useFrame(callback: RenderCallback, renderPriority: number = 0):
return null
}

/**
* Executes a callback in a given update stage.
* Uses the stage instance to identify which stage to target in the lifecycle.
*/
export function useUpdate(callback: UpdateCallback, stage: StageTypes = Stages.Update): void {
const store = useStore()
const stages = store.getState().internal.stages
// Memoize ref
const ref = useMutableCallback(callback)
// Throw an error if a stage does not exist in the lifecycle
if (!stages.includes(stage)) throw new Error(`An invoked stage does not exist in the lifecycle.`)
// Subscribe on mount, unsubscribe on unmount
useIsomorphicLayoutEffect(() => stage.add(ref, store), [stage])
}

/**
* Returns a node graph of an object with named nodes & materials.
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
Expand Down
8 changes: 0 additions & 8 deletions packages/fiber/src/core/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,15 @@ export type {
export { extend, reconciler } from './reconciler'
export type { ReconcilerRoot, GLProps, CameraProps, RenderProps, InjectState } from './renderer'
export { _roots, render, createRoot, unmountComponentAtNode, createPortal } from './renderer'
export type { UpdateSubscription } from './stages'
export { Stage, FixedStage, Stages } from './stages'
export type {
Subscription,
Dpr,
Size,
Viewport,
RenderCallback,
UpdateCallback,
LegacyAlways,
FrameloopMode,
FrameloopRender,
FrameloopLegacy,
Frameloop,
Performance,
Renderer,
StageTypes,
XRManager,
RootState,
RootStore,
Expand Down
21 changes: 15 additions & 6 deletions packages/fiber/src/core/loop.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { _roots } from './renderer'
import type { RootState } from './store'
import type { RootState, Subscription } from './store'

export type GlobalRenderCallback = (timestamp: number) => void
interface SubItem {
Expand Down Expand Up @@ -54,22 +54,31 @@ export function flushGlobalEffects(type: GlobalEffectType, timestamp: number): v
}
}

let subscribers: Subscription[]
let subscription: Subscription

function update(timestamp: number, state: RootState, frame?: XRFrame) {
// Run local effects
let delta = state.clock.getDelta()

// In frameloop='never' mode, clock times are updated using the provided timestamp
if (state.frameloop === 'never' && typeof timestamp === 'number') {
delta = timestamp - state.clock.elapsedTime
state.clock.oldTime = state.clock.elapsedTime
state.clock.elapsedTime = timestamp
} else {
delta = Math.max(Math.min(delta, state.internal.maxDelta), 0)
}
// Call subscribers (useUpdate)
for (const stage of state.internal.stages) {
stage.frame(delta, frame)

// Call subscribers (useFrame)
subscribers = state.internal.subscribers
for (let i = 0; i < subscribers.length; i++) {
subscription = subscribers[i]
subscription.ref.current(subscription.store.getState(), delta, frame)
}

// Render content
if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera)

// Decrease frame count
state.internal.frames = Math.max(0, state.internal.frames - 1)
return state.frameloop === 'always' ? 1 : state.internal.frames
}
Expand Down
42 changes: 0 additions & 42 deletions packages/fiber/src/core/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
Size,
Dpr,
Performance,
Subscription,
Frameloop,
RootStore,
} from './store'
Expand All @@ -34,7 +33,6 @@ import {
getColorManagement,
} from './utils'
import { useStore } from './hooks'
import { Stage, Lifecycle, Stages } from './stages'

// Shim for OffscreenCanvas since it was removed from DOM types
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/54988
Expand Down Expand Up @@ -107,9 +105,6 @@ export interface RenderProps<TCanvas extends HTMLCanvasElement | OffscreenCanvas
onCreated?: (state: RootState) => void
/** Response for pointer clicks that have missed any target */
onPointerMissed?: (event: MouseEvent) => void
/** Create a custom lifecycle of stages */
stages?: Stage[]
render?: 'auto' | 'manual'
}

const createRendererInstance = <TCanvas extends HTMLCanvasElement | OffscreenCanvas>(
Expand All @@ -128,39 +123,6 @@ const createRendererInstance = <TCanvas extends HTMLCanvasElement | OffscreenCan
})
}

const createStages = (stages: Stage[] | undefined, store: RootStore) => {
const state = store.getState()
let subscribers: Subscription[]
let subscription: Subscription

const _stages = stages ?? Lifecycle

if (!_stages.includes(Stages.Update)) throw 'The Stages.Update stage is required for R3F.'
if (!_stages.includes(Stages.Render)) throw 'The Stages.Render stage is required for R3F.'

state.set(({ internal }) => ({ internal: { ...internal, stages: _stages } }))

// Add useFrame loop to update stage
const frameCallback = {
current(state: RootState, delta: number, frame?: XRFrame | undefined) {
subscribers = state.internal.subscribers
for (let i = 0; i < subscribers.length; i++) {
subscription = subscribers[i]
subscription.ref.current(subscription.store.getState(), delta, frame)
}
},
}
Stages.Update.add(frameCallback, store)

// Add render callback to render stage
const renderCallback = {
current(state: RootState) {
if (state.internal.render === 'auto' && state.gl.render) state.gl.render(state.scene, state.camera)
},
}
Stages.Render.add(renderCallback, store)
}

export interface ReconcilerRoot<TCanvas extends HTMLCanvasElement | OffscreenCanvas> {
configure: (config?: RenderProps<TCanvas>) => ReconcilerRoot<TCanvas>
render: (element: React.ReactNode) => RootStore
Expand Down Expand Up @@ -247,7 +209,6 @@ export function createRoot<TCanvas extends HTMLCanvasElement | OffscreenCanvas>(
raycaster: raycastOptions,
camera: cameraOptions,
onPointerMissed,
stages,
} = props

let state = store.getState()
Expand Down Expand Up @@ -426,9 +387,6 @@ export function createRoot<TCanvas extends HTMLCanvasElement | OffscreenCanvas>(
if (performance && !is.equ(performance, state.performance, shallowLoose))
state.set((state) => ({ performance: { ...state.performance, ...performance } }))

// Create update stages. Only do this once on init
if (state.internal.stages.length === 0) createStages(stages, store)

// Set locals
onCreated = onCreatedCallback
configured = true
Expand Down
Loading

0 comments on commit 9ba7697

Please sign in to comment.