perf(ui): optimize checking if a field value is changed by wrapping in single selector

This commit is contained in:
psychedelicious
2025-02-16 09:29:52 +10:00
parent 2fa47cf270
commit ce286363d0
3 changed files with 34 additions and 35 deletions

View File

@@ -1,19 +1,29 @@
import { useAppDispatch } from 'app/store/storeHooks'; import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useInputFieldTemplate } from 'features/nodes/hooks/useInputFieldTemplate'; import { useInputFieldTemplate } from 'features/nodes/hooks/useInputFieldTemplate';
import { useInputFieldValue } from 'features/nodes/hooks/useInputFieldValue';
import { fieldValueReset } from 'features/nodes/store/nodesSlice'; import { fieldValueReset } from 'features/nodes/store/nodesSlice';
import { selectNodesSlice } from 'features/nodes/store/selectors';
import { isInvocationNode } from 'features/nodes/types/invocation';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
export const useInputFieldDefaultValue = (nodeId: string, fieldName: string) => { export const useInputFieldDefaultValue = (nodeId: string, fieldName: string) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const value = useInputFieldValue(nodeId, fieldName);
const fieldTemplate = useInputFieldTemplate(nodeId, fieldName); const fieldTemplate = useInputFieldTemplate(nodeId, fieldName);
const selectIsChanged = useMemo(
const isValueChanged = useMemo(() => { () =>
return !isEqual(value, fieldTemplate.default); createSelector(selectNodesSlice, (nodes) => {
}, [value, fieldTemplate.default]); const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const value = node.data.inputs[fieldName]?.value;
return !isEqual(value, fieldTemplate.default);
}),
[fieldName, fieldTemplate.default, nodeId]
);
const isValueChanged = useAppSelector(selectIsChanged);
const resetToDefaultValue = useCallback(() => { const resetToDefaultValue = useCallback(() => {
dispatch(fieldValueReset({ nodeId, fieldName, value: fieldTemplate.default })); dispatch(fieldValueReset({ nodeId, fieldName, value: fieldTemplate.default }));

View File

@@ -1,8 +1,9 @@
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useInputFieldValue } from 'features/nodes/hooks/useInputFieldValue';
import { fieldValueReset } from 'features/nodes/store/nodesSlice'; import { fieldValueReset } from 'features/nodes/store/nodesSlice';
import { selectNodesSlice } from 'features/nodes/store/selectors';
import { selectWorkflowSlice } from 'features/nodes/store/workflowSlice'; import { selectWorkflowSlice } from 'features/nodes/store/workflowSlice';
import { isInvocationNode } from 'features/nodes/types/invocation';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
@@ -21,11 +22,22 @@ export const useInputFieldInitialFormValue = (elementId: string, nodeId: string,
[elementId] [elementId]
); );
const initialValue = useAppSelector(selectInitialValue); const initialValue = useAppSelector(selectInitialValue);
const value = useInputFieldValue(nodeId, fieldName); const selectIsChanged = useMemo(
const isValueChanged = useMemo( () =>
() => initialValue !== uniqueNonexistentValue && !isEqual(value, initialValue), createSelector(selectNodesSlice, (nodes) => {
[value, initialValue] if (initialValue === uniqueNonexistentValue) {
return false;
}
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
const value = node.data.inputs[fieldName]?.value;
return !isEqual(value, initialValue);
}),
[fieldName, initialValue, nodeId]
); );
const isValueChanged = useAppSelector(selectIsChanged);
const resetToInitialValue = useCallback(() => { const resetToInitialValue = useCallback(() => {
if (initialValue === uniqueNonexistentValue) { if (initialValue === uniqueNonexistentValue) {
return; return;

View File

@@ -1,23 +0,0 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { selectNodesSlice } from 'features/nodes/store/selectors';
import { isInvocationNode } from 'features/nodes/types/invocation';
import { useMemo } from 'react';
export const useInputFieldValue = (nodeId: string, fieldName: string) => {
const selector = useMemo(
() =>
createSelector(selectNodesSlice, (nodes) => {
const node = nodes.nodes.find((node) => node.id === nodeId);
if (!isInvocationNode(node)) {
return;
}
return node?.data.inputs[fieldName]?.value;
}),
[fieldName, nodeId]
);
const value = useAppSelector(selector);
return value;
};