-
-
Notifications
You must be signed in to change notification settings - Fork 137
/
Copy pathusePlotly.js
50 lines (41 loc) · 1.52 KB
/
usePlotly.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { useLayoutEffect, useState, useMemo } from 'react';
import { head, prop, compose, pick, objOf, mergeDeepRight } from 'ramda';
import { stream, scan } from 'flyd';
/**
* A simple debouncing function
*/
const debounce = (fn, delay) => {
let timeout;
return function (...args) {
const functionCall = () => fn.apply(this, args);
timeout && clearTimeout(timeout);
timeout = setTimeout(functionCall, delay);
};
};
const getSizeForLayout = compose(objOf('layout'), pick(['width', 'height']), prop('contentRect'), head);
export default function usePlotly() {
const updates = useMemo(stream, []);
const appendData = useMemo(stream, []);
const plotlyState = useMemo(
() => scan(mergeDeepRight, { data: [], config: {}, layout: {} }, updates),
[]
);
const observer = new ResizeObserver(debounce(compose(updates, getSizeForLayout), 100));
const [internalRef, setRef] = useState(null);
useLayoutEffect(() => {
if (internalRef) {
observer.observe(internalRef);
const endS = plotlyState.map(state => {
Plotly.react(internalRef, state);
});
const endAppend = appendData.map(({ data, tracePos }) => Plotly.extendTraces(internalRef, data, tracePos));
return () => {
Plotly.purge(internalRef);
observer.unobserve(internalRef);
endAppend.end(true);
endS.end(true);
};
}
}, [internalRef, plotlyState, updates, appendData]);
return { ref: setRef, updates, appendData };
}