Fix the recursion issue with theatric
This commit is contained in:
parent
97ab020bfb
commit
00bb2d3310
2 changed files with 33 additions and 9 deletions
|
@ -1,4 +1,4 @@
|
|||
import {button, initialize, useControls} from 'theatric'
|
||||
import {button, initialize, types, useControls} from 'theatric'
|
||||
import {render} from 'react-dom'
|
||||
import React, {useState} from 'react'
|
||||
import state from './state.json'
|
||||
|
@ -32,11 +32,12 @@ function App() {
|
|||
baz: button(() => console.log($get((p) => p.bar))),
|
||||
})
|
||||
|
||||
const {another, panel, yo} = useControls(
|
||||
const {another, panel, col, yo} = useControls(
|
||||
{
|
||||
another: '',
|
||||
panel: '',
|
||||
yo: 0,
|
||||
yo: types.number(0),
|
||||
col: types.rgba(),
|
||||
},
|
||||
{panel: 'My panel'},
|
||||
)
|
||||
|
@ -54,7 +55,7 @@ function App() {
|
|||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<div>{JSON.stringify(bar)}</div>
|
||||
{/* <div>{JSON.stringify(bar)}</div> */}
|
||||
<SomeComponent id="first" />
|
||||
<SomeComponent id="second" />
|
||||
<button
|
||||
|
@ -73,6 +74,7 @@ function App() {
|
|||
</button>
|
||||
{showComponent && <SomeComponent id="hidden" />}
|
||||
{yo}
|
||||
{JSON.stringify(col)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {getProject} from '@theatre/core'
|
|||
import type {Pointer} from '@theatre/dataverse'
|
||||
import {isPointer} from '@theatre/dataverse'
|
||||
import studio from '@theatre/studio'
|
||||
import isEqualWith from 'lodash-es/isEqualWith'
|
||||
import isEqual from 'lodash-es/isEqual'
|
||||
import {useEffect, useMemo, useState, useRef} from 'react'
|
||||
|
||||
|
@ -33,6 +34,17 @@ const maybeTransaction =
|
|||
|
||||
let _projectConfig: IProjectConfig['state'] | undefined = undefined
|
||||
|
||||
// used for comparing config objects, to avoid re-rendering when the config object is recreated
|
||||
// but the values are the same except for functions
|
||||
function equalityCheckWithFunctionsAlwaysEqual(
|
||||
a: unknown,
|
||||
b: unknown,
|
||||
): boolean | undefined {
|
||||
if (typeof a === 'function' && typeof b === 'function') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
export function initialize(config: IProjectConfig) {
|
||||
if (_projectConfig !== undefined) {
|
||||
console.warn(
|
||||
|
@ -100,12 +112,20 @@ export function useControls<Config extends ControlsAndButtons>(
|
|||
*/
|
||||
const configRef = useRef(config)
|
||||
const _config = useMemo(() => {
|
||||
if (isEqual(config, configRef.current)) {
|
||||
return configRef.current
|
||||
} else {
|
||||
let currentConfig = configRef.current
|
||||
|
||||
if (
|
||||
!isEqualWith(
|
||||
config,
|
||||
configRef.current,
|
||||
equalityCheckWithFunctionsAlwaysEqual,
|
||||
)
|
||||
) {
|
||||
configRef.current = config
|
||||
return config
|
||||
currentConfig = config
|
||||
}
|
||||
|
||||
return currentConfig
|
||||
}, [config])
|
||||
|
||||
const {folder} = options
|
||||
|
@ -142,7 +162,9 @@ export function useControls<Config extends ControlsAndButtons>(
|
|||
Object.entries(buttons).map(([key, value]) => [
|
||||
`${folder ? `${folder}: ` : ''}${key}`,
|
||||
() => {
|
||||
value.onClick()
|
||||
// the value of the button is a function, so we can't use it as a dependency, but we can use it as a ref
|
||||
// @ts-ignore
|
||||
configRef.current[key].onClick?.()
|
||||
},
|
||||
]),
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue