Skip to content

Commit

Permalink
fix(renderer): update instance on commitupdate, cleanup prop filter
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyJasonBennett committed Jul 22, 2022
1 parent 3aea5b2 commit ae3c219
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 28 deletions.
17 changes: 10 additions & 7 deletions packages/fiber/src/core/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
const childIndex = parent.children.indexOf(child)
if (childIndex !== -1) parent.children.splice(childIndex, 1)

if (child.props.attach) detach(parent, child)
else if (child.object.isObject3D && parent.object.isObject3D) {
if (child.props.attach) {
detach(parent, child)
} else if (child.object.isObject3D && parent.object.isObject3D) {
parent.object.remove(child.object)
removeInteractivity(child.root, child.object as unknown as THREE.Object3D)
}
Expand Down Expand Up @@ -286,14 +287,14 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
insertInContainerBefore: () => {},
getRootHostContext: () => null,
getChildHostContext: (parentHostContext) => parentHostContext,
prepareUpdate(instance, type, oldProps, newProps) {
prepareUpdate(instance, _type, oldProps, newProps) {
// Reconstruct primitives if object prop changes
if (type === 'primitive' && oldProps.object !== newProps.object) return [true]
if (instance.type === 'primitive' && oldProps.object !== newProps.object) return [true]
// Reconstruct elements if args change
if (newProps.args?.some((value, index) => value !== oldProps.args?.[index])) return [true]

// Create a diff-set, flag if there are any changes
const changedProps = diffProps(instance, newProps, oldProps, true)
const changedProps = diffProps(newProps, oldProps, true)
if (Object.keys(changedProps).length) return [false, changedProps]

// Otherwise do not touch the instance
Expand All @@ -303,9 +304,11 @@ function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?:
const [reconstruct, changedProps] = diff!

// Reconstruct when args or <primitive object={...} have changes
if (reconstruct) switchInstance(instance, type, newProps, fiber)
if (reconstruct) return switchInstance(instance, type, newProps, fiber)

// Otherwise just overwrite props
else applyProps(instance.object, changedProps)
Object.assign(instance.props, newProps)
applyProps(instance.object, changedProps)
},
finalizeInitialChildren: () => true,
commitMount: commitInstance,
Expand Down
40 changes: 19 additions & 21 deletions packages/fiber/src/core/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as THREE from 'three'
import * as React from 'react'
import { EventHandlers } from './events'
import { AttachType, Instance, InstanceProps } from './renderer'
import { Instance, InstanceProps } from './renderer'
import { Dpr, RootState, Size } from './store'

export type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera
Expand Down Expand Up @@ -177,24 +177,26 @@ export function detach(parent: Instance, child: Instance) {
}

const DEFAULT = '__default'
const REACT_RESERVED_PROPS = ['children', 'key', 'ref']
const INSTANCE_RESERVED_PROPS = ['args', 'object', 'dispose', 'attach']
const RESERVED_PROPS = [
// React internal props
'children',
'key',
'ref',
// Instance props
'args',
'dispose',
'attach',
// 'object', -- internal to primitives
]

// This function prepares a set of changes to be applied to the instance
export function diffProps(
instance: Instance,
newProps: InstanceProps,
oldProps: InstanceProps,
remove = false,
): InstanceProps {
export function diffProps(newProps: InstanceProps, oldProps: InstanceProps, remove = false): InstanceProps {
const changedProps: InstanceProps = {}

// Sort through props
for (const key in newProps) {
// Skip reserved keys
if (REACT_RESERVED_PROPS.includes(key as typeof REACT_RESERVED_PROPS[number])) continue
// Skip primitives
if (instance.type === 'primitive' && key === 'object') continue
if (RESERVED_PROPS.includes(key)) continue
// Skip if props match
if (is.equ(newProps[key], oldProps[key])) continue

Expand All @@ -205,7 +207,7 @@ export function diffProps(
// Catch removed props, prepend them so they can be reset or removed
if (remove) {
for (const key in oldProps) {
if (REACT_RESERVED_PROPS.includes(key)) continue
if (RESERVED_PROPS.includes(key)) continue
else if (!newProps.hasOwnProperty(key)) changedProps[key] = DEFAULT + 'remove'
}
}
Expand All @@ -214,20 +216,16 @@ export function diffProps(
}

// This function applies a set of changes to the instance
export function applyProps(object: any, newProps: any, oldProps?: any) {
export function applyProps(object: any, props: any) {
const instance = object.__r3f as Instance | undefined
const rootState = instance?.root.getState()
const prevHandlers = instance?.eventCount

for (const prop in newProps) {
let value = newProps[prop]
for (const prop in props) {
let value = props[prop]

// Don't mutate reserved keys
if (REACT_RESERVED_PROPS.includes(prop as typeof REACT_RESERVED_PROPS[number])) continue
if (INSTANCE_RESERVED_PROPS.includes(prop as typeof INSTANCE_RESERVED_PROPS[number])) continue

// Don't mutate unchanged keys
if (newProps[prop] === oldProps?.[prop]) continue
if (RESERVED_PROPS.includes(prop)) continue

// Deal with pointer events ...
if (instance && /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(prop)) {
Expand Down

0 comments on commit ae3c219

Please sign in to comment.