feat(react): Support Mutiple useOnSelectionChange Hook subscribers

This commit is contained in:
spky
2023-11-03 00:48:46 +01:00
parent 428fced240
commit bbd5973d66
6 changed files with 69 additions and 686 deletions
@@ -1,5 +1,5 @@
import { useCallback } from 'react'; import { useCallback, useState } from 'react';
import { import {
ReactFlow, ReactFlow,
addEdge, addEdge,
ReactFlowProvider, ReactFlowProvider,
@@ -35,9 +35,9 @@ const initialEdges: Edge[] = [
}, },
]; ];
const SelectionLogger = () => { const SelectionLogger = ({ id }: { id: string }) => {
const onChange = useCallback(({ nodes, edges }: OnSelectionChangeParams) => { const onChange = useCallback(({ nodes, edges }: OnSelectionChangeParams) => {
console.log(nodes, edges); console.log(id, nodes, edges);
}, []); }, []);
useOnSelectionChange({ useOnSelectionChange({
@@ -63,14 +63,23 @@ const Flow = () => {
); );
}; };
const WrappedFlow = () => ( const WrappedFlow = () => {
<ReactFlowProvider> const [secondLoggerActive, setSecondLoggerActive] = useState<boolean>(false);
<Flow />
<SelectionLogger /> const toggleSecondLogger = () => {
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}> setSecondLoggerActive(!secondLoggerActive);
<input type={'text'} placeholder={'name'} /> };
</div>
</ReactFlowProvider> return (
); <ReactFlowProvider>
<Flow />
<SelectionLogger id="Logger 1" />
{secondLoggerActive && <SelectionLogger id="Logger 2" />}
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
<button onClick={toggleSecondLogger}>{secondLoggerActive ? 'Disable' : 'Enable'} Logger 2</button>
</div>
</ReactFlowProvider>
);
};
export default WrappedFlow; export default WrappedFlow;
@@ -33,7 +33,7 @@ const SelectionListener = memo(({ onSelectionChange }: SelectionListenerProps) =
useEffect(() => { useEffect(() => {
const params = { nodes: selectedNodes, edges: selectedEdges }; const params = { nodes: selectedNodes, edges: selectedEdges };
onSelectionChange?.(params); onSelectionChange?.(params);
store.getState().onSelectionChange?.(params); store.getState().onSelectionChange.forEach((fn) => fn(params));
}, [selectedNodes, selectedEdges, onSelectionChange]); }, [selectedNodes, selectedEdges, onSelectionChange]);
return null; return null;
@@ -4,14 +4,19 @@ import { useStoreApi } from './useStore';
import type { OnSelectionChangeFunc } from '../types'; import type { OnSelectionChangeFunc } from '../types';
export type UseOnSelectionChangeOptions = { export type UseOnSelectionChangeOptions = {
onChange?: OnSelectionChangeFunc; onChange: OnSelectionChangeFunc;
}; };
function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) { function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) {
const store = useStoreApi(); const store = useStoreApi();
useEffect(() => { useEffect(() => {
store.setState({ onSelectionChange: onChange }); const addedOnSelectionChange = [...store.getState().onSelectionChange, onChange];
store.setState({ onSelectionChange: addedOnSelectionChange });
return () => {
const removedOnSelectionChange = store.getState().onSelectionChange.filter((fn) => fn !== onChange);
store.setState({ onSelectionChange: removedOnSelectionChange });
};
}, [onChange]); }, [onChange]);
} }
+1
View File
@@ -92,6 +92,7 @@ const getInitialState = ({
connectionRadius: 20, connectionRadius: 20,
onError: () => null, onError: () => null,
isValidConnection: undefined, isValidConnection: undefined,
onSelectionChange: [],
lib: 'react', lib: 'react',
}; };
+1 -1
View File
@@ -124,7 +124,7 @@ export type ReactFlowStore = {
onViewportChange?: OnViewportChange; onViewportChange?: OnViewportChange;
onViewportChangeEnd?: OnViewportChange; onViewportChangeEnd?: OnViewportChange;
onSelectionChange?: OnSelectionChangeFunc; onSelectionChange: OnSelectionChangeFunc[];
ariaLiveMessage: string; ariaLiveMessage: string;
autoPanOnConnect: boolean; autoPanOnConnect: boolean;
+36 -668
View File
File diff suppressed because it is too large Load Diff