storybook-addon-recoil-flow
Version:
Shows a graph of the current recoil state
59 lines (58 loc) • 2.47 kB
JavaScript
import { useRef } from "react";
import { useState, useEffect } from "react";
import { useRecoilSnapshot } from "recoil";
import justCompare from "just-compare";
import mix from "mix-css-color";
export const useRecoilNodesAndEdges = () => {
const snapshot = useRecoilSnapshot();
const [nodes, setNodes] = useState([]);
const [edges, setEdges] = useState([]);
const previousContentRef = useRef({});
const framesSinceLastChangeRef = useRef({});
useEffect(() => {
const snapshotNodes = Array.from(snapshot.getNodes_UNSTABLE());
setNodes(snapshotNodes.map((snapshotNode) => {
var _a;
const { key } = snapshotNode;
const value = snapshot.getLoadable(snapshotNode);
const info = snapshot.getInfo_UNSTABLE(snapshotNode);
const previousContents = previousContentRef.current[key];
const hasChanged = previousContents !== undefined &&
!justCompare(previousContentRef.current[key], value.contents);
previousContentRef.current[key] = value.contents;
let framesSinceLastChange = (_a = framesSinceLastChangeRef.current[key]) !== null && _a !== void 0 ? _a : Infinity;
if (hasChanged) {
framesSinceLastChange = 0;
}
else {
framesSinceLastChange += 1;
}
framesSinceLastChangeRef.current[key] = framesSinceLastChange;
const colourShift = Math.max(0, 3 - framesSinceLastChange) / 3;
return {
id: key,
label: key,
fill: mix("#EFC580", "#AACBD2", colourShift * 100).hex,
size: hasChanged ? 12 : 8,
data: {
contents: value.contents,
lastUpdate: framesSinceLastChange,
type: info.type,
},
};
}));
setEdges(snapshotNodes.flatMap((snapshotNode) => {
const info = snapshot.getInfo_UNSTABLE(snapshotNode);
const deps = Array.from(info.deps);
const componentSubs = Array.from(info.subscribers.components);
return deps.map((dep) => ({
id: `${snapshotNode.key}-${dep.key}`,
source: dep.key,
target: snapshotNode.key,
animated: true,
size: 2,
}));
}));
}, [snapshot]);
return { nodes, edges };
};