Fix the recursion issue with theatric

This commit is contained in:
Aria Minaei 2023-01-24 18:45:41 +01:00
parent 97ab020bfb
commit 00bb2d3310
2 changed files with 33 additions and 9 deletions

View file

@ -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>
)
}

View file

@ -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?.()
},
]),
),