Fix: Re-render the panels when object identity change
This fixes the pesky "Argument 'der' in 'useDerivation(der)' should not change between renders."
This commit is contained in:
parent
4596c2233c
commit
c58bc694ee
5 changed files with 32 additions and 4 deletions
|
@ -40,6 +40,9 @@ const createEditable = <Keys extends keyof JSX.IntrinsicElements>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: detect if `editable()` is being called in the body of a react component, which is a common
|
||||||
|
// mistake. If it is, throw an error.
|
||||||
|
|
||||||
return forwardRef(
|
return forwardRef(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
|
16
theatre/shared/src/utils/uniqueKeyForAnyObject.ts
Normal file
16
theatre/shared/src/utils/uniqueKeyForAnyObject.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
const cache = new WeakMap<object, string>()
|
||||||
|
let nextKey = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns a unique string key for any JS object. This is useful for key-ing react components
|
||||||
|
* based on the identity of an object.
|
||||||
|
*
|
||||||
|
* @param obj - any JS object
|
||||||
|
* @returns a unique string key for the object
|
||||||
|
*/
|
||||||
|
export default function uniqueKeyForAnyObject(obj: object): string {
|
||||||
|
if (!cache.has(obj)) {
|
||||||
|
cache.set(obj, (nextKey++).toString())
|
||||||
|
}
|
||||||
|
return cache.get(obj)!
|
||||||
|
}
|
|
@ -118,6 +118,7 @@ const DetailPanel: React.FC<{}> = (props) => {
|
||||||
const selection = getOutlineSelection()
|
const selection = getOutlineSelection()
|
||||||
|
|
||||||
const obj = selection.find(isSheetObject)
|
const obj = selection.find(isSheetObject)
|
||||||
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
import React, {useMemo} from 'react'
|
import React from 'react'
|
||||||
import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
||||||
import type {Pointer} from '@theatre/dataverse'
|
import type {Pointer} from '@theatre/dataverse'
|
||||||
import type {$FixMe} from '@theatre/shared/utils/types'
|
import type {$FixMe} from '@theatre/shared/utils/types'
|
||||||
import DeterminePropEditorForDetail from './DeterminePropEditorForDetail'
|
import DeterminePropEditorForDetail from './DeterminePropEditorForDetail'
|
||||||
import {useVal} from '@theatre/react'
|
import {useVal} from '@theatre/react'
|
||||||
|
import uniqueKeyForAnyObject from '@theatre/shared/utils/uniqueKeyForAnyObject'
|
||||||
|
|
||||||
const ObjectDetails: React.FC<{
|
const ObjectDetails: React.FC<{
|
||||||
/** TODO: add support for multiple objects (it would show their common props) */
|
/** TODO: add support for multiple objects (it would show their common props) */
|
||||||
objects: [SheetObject]
|
objects: [SheetObject]
|
||||||
}> = ({objects}) => {
|
}> = ({objects}) => {
|
||||||
const obj = objects[0]
|
const obj = objects[0]
|
||||||
const key = useMemo(() => JSON.stringify(obj.address), [obj])
|
|
||||||
const config = useVal(obj.template.configPointer)
|
const config = useVal(obj.template.configPointer)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DeterminePropEditorForDetail
|
<DeterminePropEditorForDetail
|
||||||
key={key}
|
// we don't use the object's address as the key because if a user calls `sheet.detachObject(key)` and later
|
||||||
|
// calls `sheet.object(key)` with the same key, we want to re-render the object details panel.
|
||||||
|
key={uniqueKeyForAnyObject(obj)}
|
||||||
obj={obj}
|
obj={obj}
|
||||||
pointerToProp={obj.propsP as Pointer<$FixMe>}
|
pointerToProp={obj.propsP as Pointer<$FixMe>}
|
||||||
propConfig={config}
|
propConfig={config}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react'
|
||||||
import LeftSheetObjectRow from './SheetObjectRow'
|
import LeftSheetObjectRow from './SheetObjectRow'
|
||||||
import AnyCompositeRow from './AnyCompositeRow'
|
import AnyCompositeRow from './AnyCompositeRow'
|
||||||
import {setCollapsedSheetItem} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/setCollapsedSheetObjectOrCompoundProp'
|
import {setCollapsedSheetItem} from '@theatre/studio/panels/SequenceEditorPanel/DopeSheet/setCollapsedSheetObjectOrCompoundProp'
|
||||||
|
import uniqueKeyForAnyObject from '@theatre/shared/utils/uniqueKeyForAnyObject'
|
||||||
|
|
||||||
const SheetRow: React.VFC<{
|
const SheetRow: React.VFC<{
|
||||||
leaf: SequenceEditorTree_Sheet
|
leaf: SequenceEditorTree_Sheet
|
||||||
|
@ -23,7 +24,12 @@ const SheetRow: React.VFC<{
|
||||||
>
|
>
|
||||||
{leaf.children.map((sheetObjectLeaf) => (
|
{leaf.children.map((sheetObjectLeaf) => (
|
||||||
<LeftSheetObjectRow
|
<LeftSheetObjectRow
|
||||||
key={'sheetObject-' + sheetObjectLeaf.sheetObject.address.objectKey}
|
key={
|
||||||
|
'sheetObject-' +
|
||||||
|
// we don't use the object's address as the key because if a user calls `sheet.detachObject(key)` and later
|
||||||
|
// calls `sheet.object(key)` with the same key, we want to re-render this row.
|
||||||
|
uniqueKeyForAnyObject(sheetObjectLeaf.sheetObject)
|
||||||
|
}
|
||||||
leaf={sheetObjectLeaf}
|
leaf={sheetObjectLeaf}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
Loading…
Reference in a new issue