diff --git a/src/common/resources/entity/trait-pane.jsx b/src/common/resources/entity/trait-pane.jsx index 6b3a33b..4980d28 100644 --- a/src/common/resources/entity/trait-pane.jsx +++ b/src/common/resources/entity/trait-pane.jsx @@ -1,8 +1,9 @@ import {mapObject} from '@avocado/core'; import {lookupTrait} from '@avocado/entity'; import {all as allTraitComponents} from '@avocado/entity/trait/trait-components.scwp'; +import memoize from 'lodash.memoize'; import PropTypes from 'prop-types'; -import React, {useMemo} from 'react'; +import React from 'react'; import {useDispatch} from 'react-redux'; import {registerHooks} from 'scwp'; @@ -10,20 +11,24 @@ import Value from '~/client/value'; import {setTraitProperty} from './state'; -let TraitComponents; -const ensureTraitComponents = () => { - if (!TraitComponents) { - TraitComponents = Object.values(allTraitComponents()).reduce((r, M) => { - const {default: TraitComponent} = M; - return {...r, [TraitComponent.type]: TraitComponent}; - }, {}); - } -}; +const traitComponents = memoize(() => { + return Object.values(allTraitComponents()).reduce((r, M) => { + const {default: TraitComponent} = M; + return {...r, [TraitComponent.type]: TraitComponent}; + }, {}); +}); -const makeTraitPaneRenderer = (context, dispatch, entity, target, traitType) => (trait) => { - ensureTraitComponents(); +const TraitPane = (props) => { + const { + context, + entity, + target, + trait, + type: traitType, + } = props; + const dispatch = useDispatch(); const {params, state} = trait; - const {[traitType]: TraitComponent} = TraitComponents; + const {[traitType]: TraitComponent} = traitComponents; const Trait = lookupTrait(traitType); if (!Trait) { return null; @@ -67,26 +72,6 @@ const makeTraitPaneRenderer = (context, dispatch, entity, target, traitType) => ); }; -const TraitPane = (props) => { - const { - context, - entity, - target, - trait, - type, - } = props; - const dispatch = useDispatch(); - // TODO: dependency on context is too noisy - const renderTraitPane = useMemo( - () => makeTraitPaneRenderer(context, dispatch, entity, target, type), - [context, dispatch, entity, target, type], - ); - return useMemo( - () => renderTraitPane(trait), - [renderTraitPane, trait], - ); -}; - TraitPane.propTypes = { context: PropTypes.shape({}).isRequired, target: PropTypes.string.isRequired, @@ -99,6 +84,9 @@ export default TraitPane; if (module.hot) { registerHooks({ autoreg$accept: (type, M) => { + if ('trait-component' === type) { + traitComponents.cache.clear(); + } if ('type-renderer' === type) { module.hot.invalidate(); }