Memoize comopnents of deriver()
This commit is contained in:
parent
558882ff0a
commit
86dd2cbf86
1 changed files with 38 additions and 50 deletions
|
@ -4,7 +4,6 @@ import {useDerivation} from '@theatre/react'
|
||||||
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
||||||
import React, {useMemo, useRef} from 'react'
|
import React, {useMemo, useRef} from 'react'
|
||||||
import {invariant} from './invariant'
|
import {invariant} from './invariant'
|
||||||
import {emptyArray} from '@theatre/shared/utils'
|
|
||||||
|
|
||||||
type DeriveAll<T> = IDerivation<
|
type DeriveAll<T> = IDerivation<
|
||||||
{
|
{
|
||||||
|
@ -36,23 +35,6 @@ function deriveAllD<T extends Record<string, $<any>> | $<any>[]>(
|
||||||
}) as $IntentionalAny
|
}) as $IntentionalAny
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useReactPrism(
|
|
||||||
fn: () => React.ReactNode,
|
|
||||||
deps: readonly any[] = emptyArray,
|
|
||||||
): React.ReactElement {
|
|
||||||
const derivation = useMemo(() => prism(fn), deps)
|
|
||||||
return <DeriveElement der={derivation} />
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reactPrism(fn: () => React.ReactNode): React.ReactElement {
|
|
||||||
return <DeriveElement der={prism(fn)} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeriveElement(props: {der: IDerivation<React.ReactNode>}) {
|
|
||||||
const node = useDerivation(props.der)
|
|
||||||
return <>{node}</>
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This is only used for type checking to make sure the APIs are used properly */
|
/** This is only used for type checking to make sure the APIs are used properly */
|
||||||
interface TSErrors<M> extends Error {}
|
interface TSErrors<M> extends Error {}
|
||||||
|
|
||||||
|
@ -76,41 +58,47 @@ type ReactDeriver<Props extends {}> = (
|
||||||
export function deriver<Props extends {}>(
|
export function deriver<Props extends {}>(
|
||||||
Component: React.ComponentType<Props>,
|
Component: React.ComponentType<Props>,
|
||||||
): ReactDeriver<Props> {
|
): ReactDeriver<Props> {
|
||||||
return React.forwardRef(function deriverRender(
|
const finalComp = React.memo(
|
||||||
props: Record<string, $IntentionalAny>,
|
React.forwardRef(function deriverRender(
|
||||||
ref,
|
props: Record<string, $IntentionalAny>,
|
||||||
) {
|
|
||||||
let observableArr = []
|
|
||||||
const observables: Record<string, IDerivation<$IntentionalAny>> = {}
|
|
||||||
const normalProps: Record<string, $IntentionalAny> = {
|
|
||||||
ref,
|
ref,
|
||||||
}
|
) {
|
||||||
for (const key in props) {
|
let observableArr = []
|
||||||
const value = props[key]
|
const observables: Record<string, IDerivation<$IntentionalAny>> = {}
|
||||||
if (isDerivation(value)) {
|
const normalProps: Record<string, $IntentionalAny> = {
|
||||||
observableArr.push(value)
|
ref,
|
||||||
observables[key] = value
|
}
|
||||||
} else {
|
for (const key in props) {
|
||||||
normalProps[key] = value
|
const value = props[key]
|
||||||
|
if (isDerivation(value)) {
|
||||||
|
observableArr.push(value)
|
||||||
|
observables[key] = value
|
||||||
|
} else {
|
||||||
|
normalProps[key] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const initialCount = useRef(observableArr.length)
|
const initialCount = useRef(observableArr.length)
|
||||||
invariant(
|
invariant(
|
||||||
initialCount.current === observableArr.length,
|
initialCount.current === observableArr.length,
|
||||||
`expect same number of observable props on every invocation of deriver wrapped component.`,
|
`expect same number of observable props on every invocation of deriver wrapped component.`,
|
||||||
{initial: initialCount.current, count: observableArr.length},
|
{initial: initialCount.current, count: observableArr.length},
|
||||||
)
|
)
|
||||||
|
|
||||||
const allD = useMemo(() => deriveAllD(observables), observableArr)
|
const allD = useMemo(() => deriveAllD(observables), observableArr)
|
||||||
const observedPropState = useDerivation(allD)
|
const observedPropState = useDerivation(allD)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
observedPropState &&
|
observedPropState &&
|
||||||
React.createElement(Component, {
|
React.createElement(Component, {
|
||||||
...normalProps,
|
...normalProps,
|
||||||
...observedPropState,
|
...observedPropState,
|
||||||
} as Props)
|
} as Props)
|
||||||
)
|
)
|
||||||
})
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
finalComp.displayName = `deriver(${Component.displayName})`
|
||||||
|
|
||||||
|
return finalComp
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue