diff --git a/package.json b/package.json index 9968c5b..2b2414b 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "express-session": "^1.17.1", "express-socket.io-session": "^1.3.5", "html-entities": "1.3.1", + "immer": "^7.0.1", "memorystore": "^1.6.2", "prop-types": "^15", "react": "16.8.6", diff --git a/src/client/components/traits.jsx b/src/client/components/traits.jsx index 56f59dc..2d4d359 100644 --- a/src/client/components/traits.jsx +++ b/src/client/components/traits.jsx @@ -2,8 +2,9 @@ import {compose, mapObject} from '@avocado/core'; import {all} from '@avocado/entity/trait/trait-components.scwp'; import {lookupTrait} from '@avocado/entity'; import contempo from 'contempo'; +import {produce} from 'immer'; import PropTypes from 'prop-types'; -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; // import ReactMarkdown from 'react-markdown'; import { Tab, @@ -12,7 +13,7 @@ import { TabPanel, } from 'react-tabs'; import {createSelector} from '@reduxjs/toolkit'; -import {invokeHookFlat} from 'scwp'; +import {deregisterHooks, invokeHookFlat, registerHooks} from 'scwp'; const SCROLL_MAG = 80; @@ -80,25 +81,48 @@ const makeTabSelector = (type) => createSelector( }, ); -const tabSelectorMap = new WeakMap(); - const Traits = (props) => { const {traits} = props; - if (!tabSelectorMap.has(traits)) { - tabSelectorMap.set(traits, {}); - } - const selectors = tabSelectorMap.get(traits); + const [tabSelectorMap, setTabSelectorMap] = useState({}); + useEffect(() => { + const entries = Object.entries(traits); + setTabSelectorMap(produce(tabSelectorMap, (draft) => { + for (let i = 0; i < entries.length; i++) { + const [type] = entries[i]; + if (!draft[type]) { + // eslint-disable-next-line no-param-reassign + draft[type] = new WeakMap(); + } + if (!draft[type].has(traits)) { + draft[type].set(traits, makeTabSelector(type)); + } + } + })); + const M = { + autoreg$accept: (type, M2) => { + if ('trait' === type) { + const {default: Trait} = M2; + setTabSelectorMap(produce(tabSelectorMap, (draft) => { + const traitType = Trait.type(); + if (!draft[traitType]) { + // eslint-disable-next-line no-param-reassign + draft[traitType] = new WeakMap(); + } + draft[traitType].set(traits, makeTabSelector(traitType)); + })); + } + }, + }; + registerHooks(M, __filename); + return () => deregisterHooks(M); + }, [tabSelectorMap, traits]); const [tabIndex, setTabIndex] = useState(0); let listRef; const entries = Object.entries(traits); const tabs = []; for (let i = 0; i < entries.length; i++) { const [type, trait] = entries[i]; - trait.type = type; - if (!selectors[type]) { - selectors[type] = makeTabSelector(type); - } - tabs.push([type, selectors[type](trait)]); + tabs.push([type, tabSelectorMap[type]?.get(traits)(trait)]); } return (