feat: Add post-update callback to setNode and improve node internals handling (#4696)
* ✨ (use-handle-new-value.tsx): Introduce useUpdateNodeInternals hook from reactflow to update node internals when handling new values ♻️ (flowStore.ts): Refactor set method in useFlowStore to accept a callback function to be executed after updating nodes 📝 (flowStore.ts): Update FlowStoreType to include a callback function in the update method signature * 📝 (flowStore.ts): add comment to explain deferring callback execution to ensure it runs after state updates are fully applied
This commit is contained in:
parent
d28c7f4f30
commit
a76e43fd74
3 changed files with 34 additions and 12 deletions
|
|
@ -6,6 +6,7 @@ import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||||
import { APIClassType, InputFieldType } from "@/types/api";
|
import { APIClassType, InputFieldType } from "@/types/api";
|
||||||
import { NodeType } from "@/types/flow";
|
import { NodeType } from "@/types/flow";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
|
import { useUpdateNodeInternals } from "reactflow";
|
||||||
import { mutateTemplate } from "../helpers/mutate-template";
|
import { mutateTemplate } from "../helpers/mutate-template";
|
||||||
|
|
||||||
export type handleOnNewValueType = (
|
export type handleOnNewValueType = (
|
||||||
|
|
@ -33,6 +34,7 @@ const useHandleOnNewValue = ({
|
||||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||||
|
|
||||||
const setNode = setNodeExternal ?? useFlowStore((state) => state.setNode);
|
const setNode = setNodeExternal ?? useFlowStore((state) => state.setNode);
|
||||||
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
|
||||||
|
|
@ -90,14 +92,21 @@ const useHandleOnNewValue = ({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setNode(nodeId, (oldNode) => {
|
setNode(
|
||||||
const newData = cloneDeep(oldNode.data);
|
nodeId,
|
||||||
newData.node = newNode;
|
(oldNode) => {
|
||||||
return {
|
const newData = cloneDeep(oldNode.data);
|
||||||
...oldNode,
|
newData.node = newNode;
|
||||||
data: newData,
|
return {
|
||||||
};
|
...oldNode,
|
||||||
});
|
data: newData,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
() => {
|
||||||
|
updateNodeInternals(nodeId);
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return { handleOnNewValue };
|
return { handleOnNewValue };
|
||||||
|
|
|
||||||
|
|
@ -257,13 +257,15 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
id: string,
|
id: string,
|
||||||
change: Node | ((oldState: Node) => Node),
|
change: Node | ((oldState: Node) => Node),
|
||||||
isUserChange: boolean = true,
|
isUserChange: boolean = true,
|
||||||
|
callback?: () => void,
|
||||||
) => {
|
) => {
|
||||||
let newChange =
|
let newChange =
|
||||||
typeof change === "function"
|
typeof change === "function"
|
||||||
? change(get().nodes.find((node) => node.id === id)!)
|
? change(get().nodes.find((node) => node.id === id)!)
|
||||||
: change;
|
: change;
|
||||||
get().setNodes((oldNodes) =>
|
|
||||||
oldNodes.map((node) => {
|
set((state) => {
|
||||||
|
const newNodes = state.nodes.map((node) => {
|
||||||
if (node.id === id) {
|
if (node.id === id) {
|
||||||
if (isUserChange) {
|
if (isUserChange) {
|
||||||
if ((node.data as NodeDataType).node?.frozen) {
|
if ((node.data as NodeDataType).node?.frozen) {
|
||||||
|
|
@ -273,8 +275,18 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
return newChange;
|
return newChange;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}),
|
});
|
||||||
);
|
|
||||||
|
if (callback) {
|
||||||
|
// Defer the callback execution to ensure it runs after state updates are fully applied.
|
||||||
|
queueMicrotask(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
nodes: newNodes,
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getNode: (id: string) => {
|
getNode: (id: string) => {
|
||||||
return get().nodes.find((node) => node.id === id);
|
return get().nodes.find((node) => node.id === id);
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ export type FlowStoreType = {
|
||||||
id: string,
|
id: string,
|
||||||
update: Node | ((oldState: Node) => Node),
|
update: Node | ((oldState: Node) => Node),
|
||||||
isUserChange?: boolean,
|
isUserChange?: boolean,
|
||||||
|
callback?: () => void,
|
||||||
) => void;
|
) => void;
|
||||||
getNode: (id: string) => Node | undefined;
|
getNode: (id: string) => Node | undefined;
|
||||||
deleteNode: (nodeId: string | Array<string>) => void;
|
deleteNode: (nodeId: string | Array<string>) => void;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue