import {BranchData, BranchNode, StateBranchNode} from "./StateBranchNode"; import {getGroveForReading, Grove, TreeNodeData} from "./Grove"; import {OfferData, TestableData, useNodesStore, NodesStore} from "./store"; import {TreeNode} from "./TreeNode"; import {useShallow} from "zustand/react/shallow"; import {RefObject} from "react"; import {useRaf} from "react-use"; import {TestableCompositeNode} from "./TestableCompositeNode"; export const useStoreAPI = (method: K) : NodesStore[K] => { return useNodesStore((state) => state[method]); } export const useBranch = (id: BranchData['id']) : StateBranchNode | undefined => { const branch: { current: StateBranchNode | undefined } = { current: undefined } /** * but this will, we're returning the branch data only to trigger a re-render * when the branch data changes */ useNodesStore(store => { const grove = Grove.fromState(store); branch.current = grove.get(id); if (!branch.current) { console.error('useBranch: branch not found', id); return; } // This will trigger a re-render when the branch data changes return branch.current.data; }) return branch.current; } export const useTreeNode = (id: TreeNodeData['id']) : TreeNode | undefined => { const treeNode: { current: TreeNode | undefined } = { current: undefined } /** * re-renders when the branch testable data changes */ useNodesStore(store => { const grove = Grove.fromState(store); treeNode.current = grove.get(id); if (!treeNode.current) { console.error('useTreeNode: tree node not found', id); return; } // will probably want to return the tree node object from the grove so that changes to the tree node data will trigger a re-render return treeNode.current.getId(); }) return treeNode.current } export const useTreeNodeTestable = (id: TestableData['id']) : TestableCompositeNode | undefined => { const testableNode: { current: TestableCompositeNode | undefined } = { current: undefined } /** * re-renders when the branch testable data changes */ useNodesStore(store => { const grove = Grove.fromState(store); testableNode.current = grove.get(id); if (!testableNode.current) { console.error('useTreeNodeTestable: testable node not found', id); return; } // This will trigger a re-render when the branch data changes // getData() should return the same reference to the data object in the store return testableNode.current.getTestable().getData(); }) return testableNode.current } /** * Will only re-render when the number of children of the branch changes. * @param id */ export const useBranchChildrenShallow = (id: BranchData['id']) : ChildrenType[] => { const branch: { current: StateBranchNode | undefined } = { current: undefined } const grove: { current: Grove | undefined } = { current: undefined } /** * This will trigger a re-render when the children of the branch change. */ const childIds = useNodesStore(useShallow(store => { grove.current = Grove.fromState(store) branch.current = grove.current.get(id) return branch.current ? branch.current.getChildrenIds() : []; })) const getOffer = useNodesStore(store => store.getOffer) if (!branch.current) { return [] } return branch.current.getChildren((child => { if (branch.current!.isOffers()) { return getOffer(child as string) } return grove.current!.get((child as TreeNodeData).id) })).filter(v => !!v) as ChildrenType[] }