Skip to content

Instantly share code, notes, and snippets.

@bingomanatee
Last active June 22, 2023 04:59
Show Gist options
  • Save bingomanatee/8ff933327d9e5996e70530370d7c4042 to your computer and use it in GitHub Desktop.
Save bingomanatee/8ff933327d9e5996e70530370d7c4042 to your computer and use it in GitHub Desktop.
"use client"
import { useEffect, useMemo, useRef, useState } from 'react'
import { Forest } from '@wonderlandlabs/forest'
import { leafConfig, leafI } from '@wonderlandlabs/forest/lib/types'
import { useConst } from '@chakra-ui/hooks'
type configArray = [initializer: (...args: any) => leafConfig, ...rest: any];
export default function useForest<valueType>(
config: leafConfig | configArray,
onCreate?: (leaf: leafI) => unknown,
debug?: any
)
: [value: valueType, state: leafI] {
if (debug) {
console.log('--- useForest --- running', debug);
}
const onComplete = useRef<any>(null);
const state = useConst(() => {
if (debug) {
console.log('---- useForest -- creating state', debug)
}
let initializer = config;
if (Array.isArray(config)) {
initializer = config[0](...config.slice(1))
}
const localState = new Forest(initializer);
if (onCreate) {
if (debug) {
console.log('---- useForest -- calling onCreate', onCreate, debug)
}
onComplete.current = onCreate(localState);
if (typeof (onComplete.current?.then) === 'function') {
onComplete.current.then((result) => {
onComplete.current = result
});
}
}
return localState
});
const [value, setValue] = useState<valueType>(state.value);
useEffect(() => {
if (!state) {
return;
}
if (debug) {
console.log('---- useForest -- subscribing to state', debug)
}
const sub = state.subscribe(setValue);
return () => {
sub.unsubscribe()
if (typeof onComplete.current === 'function') {
onComplete.current();
} else if (typeof (onComplete.current?.then) === 'function') {
onComplete.current.then((result) => {
if (typeof result === 'function') {
result();
}
});
}
onComplete.current = null;
};
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[state]);
return [value, state];
}
@bingomanatee
Copy link
Author

bingomanatee commented Jun 22, 2023

chakra claims useConst is less flaky than useMemo - guaranteed to only run once.

the console emits, when I add a tracer into the debug property:

--- useForest --- running PLAN EDITOR 
useForest.ts:23 ---- useForest -- creating state PLAN EDITOR 
useForest.ts:32 ---- useForest -- calling onCreate (localState)=>{
        console.log("--- PlanEditor: loading");
        localState.do.load();
    } PLAN EDITOR 
PlanEditor.tsx:16 --- PlanEditor: loading
Manager.ts:21 adding layer layers
useForest.ts:50 ---- useForest -- subscribing to state PLAN EDITOR 
useForest.ts:50 ---- useForest -- subscribing to state PLAN EDITOR 

question = why is the subscription effect running twice?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment