hooks.ts
Overview
The hooks.ts file defines a custom React hook named useHandleOperateParameters designed to manage and manipulate parameter variables related to a specific node within a graph-like data structure. This hook provides a set of utility functions to add, remove, update, and save parameters (variables) associated with a node identified by nodeId. It leverages state management via a store (useGraphStore), React hooks for memoization and callbacks, and utility functions for safe data access and unique ID generation.
The primary responsibility of this hook is to encapsulate all logic related to handling the parameters (variables) of a node's form, thereby simplifying components that consume this data by abstracting the complex state update logic and event handlers.
Detailed Explanation
Imports
getfrom lodash: Safely accesses nested object properties.React hooks:
useCallback,useMemofor performance optimizations.uuid: Generates unique identifiers for new parameter entries.Interfaces:
IGenerateParameter,IInvokeVariableto type variables.useGraphStore: Custom state store hook to access and update node data.
useHandleOperateParameters(nodeId: string)
Description
Custom React hook that manages the parameters (variables) of a node identified by nodeId. It provides handlers for adding, removing, changing, and saving parameters, exposing them alongside the current data source (list of parameters).
Parameters
Parameter | Type | Description |
|---|---|---|
| string | Unique identifier of the node whose parameters are being managed. |
Returns
An object containing:
Property | Type | Description |
|---|---|---|
|
| Handler to add a new empty parameter variable. |
| Handler to remove a parameter by its | |
| Handler to update the | |
| Handler to update the | |
| Function to save all changes to a parameter object. | |
|
| Current array of parameter variables for the node. |
Internal Logic and Methods
1. Retrieving Node and Data Source
const { getNode, updateNodeForm } = useGraphStore((state) => state);
const node = getNode(nodeId);
const dataSource: IGenerateParameter[] = useMemo(
() => get(node, 'data.form.variables', []) as IGenerateParameter[],
[node],
);
Retrieves the current node from the global store.
Extracts the
variablesarray fromnode.data.form.Memoizes
dataSourceto avoid unnecessary recalculations on re-renders unlessnodechanges.
2. changeValue
const changeValue = useCallback(
(row: IInvokeVariable, field: string, value: string) => {
const newData = [...dataSource];
const index = newData.findIndex((item) => row.id === item.id);
const item = newData[index];
newData.splice(index, 1, {
...item,
[field]: value,
});
updateNodeForm(nodeId, { variables: newData });
},
[dataSource, nodeId, updateNodeForm],
);
Generic function to update any field (
field) of a given parameter (row) with a new value.Clones the
dataSourceto avoid direct mutation.Finds the parameter by
idand replaces it with an updated copy.Updates the node form in the store with the updated variables.
3. handleComponentIdChange
const handleComponentIdChange = useCallback(
(row: IInvokeVariable) => (value: string) => {
changeValue(row, 'component_id', value);
},
[changeValue],
);
Returns a function that updates the
component_idfield for a specific parameter.
4. handleValueChange
const handleValueChange = useCallback(
(row: IInvokeVariable): ChangeEventHandler<HTMLInputElement> =>
(e) => {
changeValue(row, 'value', e.target.value);
},
[changeValue],
);
Returns an input change event handler that updates the
valuefield of a parameter.
5. handleRemove
const handleRemove = useCallback(
(id?: string) => () => {
const newData = dataSource.filter((item) => item.id !== id);
updateNodeForm(nodeId, { variables: newData });
},
[updateNodeForm, nodeId, dataSource],
);
Removes a parameter by filtering it out of the
dataSource.Updates the store with the filtered list.
6. handleAdd
const handleAdd: MouseEventHandler = useCallback(
(e) => {
e.preventDefault();
e.stopPropagation();
updateNodeForm(nodeId, {
variables: [
...dataSource,
{
id: uuid(),
key: '',
component_id: undefined,
value: '',
},
],
});
},
[dataSource, nodeId, updateNodeForm],
);
Adds a new empty parameter object with a unique
idto thevariablesarray.Prevents default mouse event behavior to avoid unwanted side effects.
7. handleSave
const handleSave = (row: IGenerateParameter) => {
const newData = [...dataSource];
const index = newData.findIndex((item) => row.id === item.id);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
updateNodeForm(nodeId, { variables: newData });
};
Updates the entire parameter object in the data source with the latest fields from
row.
Usage Example
import React from 'react';
import { useHandleOperateParameters } from './hooks';
import { IGenerateParameter } from '../../interface';
interface Props {
nodeId: string;
}
const ParameterEditor: React.FC<Props> = ({ nodeId }) => {
const {
dataSource,
handleAdd,
handleRemove,
handleComponentIdChange,
handleValueChange,
handleSave,
} = useHandleOperateParameters(nodeId);
return (
<div>
<button onClick={handleAdd}>Add Parameter</button>
{dataSource.map((param) => (
<div key={param.id}>
<input
value={param.key}
onChange={(e) =>
handleSave({ ...param, key: e.target.value })
}
/>
<input
value={param.value}
onChange={handleValueChange(param)}
/>
<button onClick={handleRemove(param.id)}>Remove</button>
</div>
))}
</div>
);
};
Implementation Details and Algorithms
Immutable Updates: To maintain React and state management best practices, all updates to the parameters array are done immutably by cloning arrays before modification.
Use of
useCallbackanduseMemo: Optimizes performance by memoizing handlers and data extraction, preventing unnecessary re-renders.Safe Data Access with
lodash/get: Avoids runtime errors due to undefined or missing nested properties when accessingnode.data.form.variables.Unique ID Generation: Uses
uuid.v4()to generate unique identifiers for new parameters, ensuring no collisions.Event Handling: Separates concerns by providing specialized handlers for different input types and actions (add, remove, update).
Interaction with Other System Parts
useGraphStore: Central to this hook is the interaction with the global graph state viauseGraphStore. The hook reads the node data and updates the node's form variables using this store.Interfaces (
IGenerateParameter,IInvokeVariable): The hook relies on these interfaces for type safety and clarity about the structure of parameter variables.UI Components: Components consuming this hook utilize the returned handlers and data to render the form fields and respond to user input.
UUID Library: Ensures new parameters have unique IDs, crucial for identification and manipulation.
Mermaid Diagram
flowchart TD
A[useHandleOperateParameters(nodeId)] --> B[getNode(nodeId)]
B --> C[dataSource = node.data.form.variables]
A --> D[changeValue(row, field, value)]
D --> E[Clone dataSource]
D --> F[Find index of row]
D --> G[Update field in copied item]
D --> H[updateNodeForm with new variables]
A --> I[handleComponentIdChange(row)]
I --> D
A --> J[handleValueChange(row)]
J --> D
A --> K[handleRemove(id)]
K --> L[Filter out param with id]
K --> H
A --> M[handleAdd(event)]
M --> N[Prevent default and stop propagation]
M --> O[Add new param with uuid]
M --> H
A --> P[handleSave(row)]
P --> E
P --> F
P --> Q[Merge row fields into item]
P --> H
Summary
The hooks.ts file encapsulates all logic for managing node parameters within a graph-based state system. By providing reusable, memoized handlers and exposing the current parameter list, it simplifies components that require parameter manipulation, while ensuring state updates are immutable and consistent. Its design follows React best practices and clean state management principles, making it an integral part of the node editing workflow in the larger application.