From df43c6ab8a0d2f80d97f69b3a4854eb360b8517b Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Sep 2025 20:35:55 +0900 Subject: [PATCH] [Chore/Refactor] Implement lazy initialization for useState calls to prevent re-computation (#26252) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: asukaminato0721 <30024051+asukaminato0721@users.noreply.github.com> --- web/app/components/app/annotation/index.tsx | 4 ++-- .../config-prompt/prompt-editor-height-resize-wrap.tsx | 2 +- .../app/configuration/config-var/config-modal/index.tsx | 2 +- .../app/configuration/hooks/use-advanced-prompt-config.ts | 4 ++-- .../base/date-and-time-picker/date-picker/index.tsx | 4 ++-- .../base/date-and-time-picker/time-picker/index.tsx | 2 +- web/app/components/base/markdown-blocks/think-block.tsx | 2 +- web/app/components/base/notion-page-selector/base.tsx | 2 +- web/app/components/base/tab-slider/index.tsx | 2 +- web/app/components/custom/custom-web-app-brand/index.tsx | 2 +- web/app/components/header/maintenance-notice.tsx | 2 +- web/app/components/signin/countdown.tsx | 2 +- web/app/components/tools/mcp/modal.tsx | 2 +- .../components/workflow/nodes/_base/hooks/use-resize-panel.ts | 2 +- .../workflow/nodes/http/hooks/use-key-value-list.ts | 2 +- .../json-schema-config-modal/json-schema-config.tsx | 2 +- .../nodes/question-classifier/components/class-item.tsx | 2 +- .../components/workflow/variable-inspect/value-content.tsx | 2 +- web/app/components/workflow/workflow-preview/index.tsx | 4 ++-- web/app/signin/invite-settings/page.tsx | 2 +- 20 files changed, 24 insertions(+), 24 deletions(-) diff --git a/web/app/components/app/annotation/index.tsx b/web/app/components/app/annotation/index.tsx index afa8732701..264b1ac727 100644 --- a/web/app/components/app/annotation/index.tsx +++ b/web/app/components/app/annotation/index.tsx @@ -38,7 +38,7 @@ const Annotation: FC = (props) => { const [isShowEdit, setIsShowEdit] = useState(false) const [annotationConfig, setAnnotationConfig] = useState(null) const [isChatApp] = useState(appDetail.mode !== 'completion') - const [controlRefreshSwitch, setControlRefreshSwitch] = useState(Date.now()) + const [controlRefreshSwitch, setControlRefreshSwitch] = useState(() => Date.now()) const { plan, enableBilling } = useProviderContext() const isAnnotationFull = enableBilling && plan.usage.annotatedResponse >= plan.total.annotatedResponse const [isShowAnnotationFullModal, setIsShowAnnotationFullModal] = useState(false) @@ -48,7 +48,7 @@ const Annotation: FC = (props) => { const [list, setList] = useState([]) const [total, setTotal] = useState(0) const [isLoading, setIsLoading] = useState(false) - const [controlUpdateList, setControlUpdateList] = useState(Date.now()) + const [controlUpdateList, setControlUpdateList] = useState(() => Date.now()) const [currItem, setCurrItem] = useState(null) const [isShowViewModal, setIsShowViewModal] = useState(false) const [selectedIds, setSelectedIds] = useState([]) diff --git a/web/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap.tsx b/web/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap.tsx index 1457a298f2..9e10db93ae 100644 --- a/web/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap.tsx +++ b/web/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap.tsx @@ -25,7 +25,7 @@ const PromptEditorHeightResizeWrap: FC = ({ }) => { const [clientY, setClientY] = useState(0) const [isResizing, setIsResizing] = useState(false) - const [prevUserSelectStyle, setPrevUserSelectStyle] = useState(getComputedStyle(document.body).userSelect) + const [prevUserSelectStyle, setPrevUserSelectStyle] = useState(() => getComputedStyle(document.body).userSelect) const [oldHeight, setOldHeight] = useState(height) const handleStartResize = useCallback((e: React.MouseEvent) => { diff --git a/web/app/components/app/configuration/config-var/config-modal/index.tsx b/web/app/components/app/configuration/config-var/config-modal/index.tsx index cecc076fe7..b0f0ea8779 100644 --- a/web/app/components/app/configuration/config-var/config-modal/index.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/index.tsx @@ -53,7 +53,7 @@ const ConfigModal: FC = ({ }) => { const { modelConfig } = useContext(ConfigContext) const { t } = useTranslation() - const [tempPayload, setTempPayload] = useState(payload || getNewVarInWorkflow('') as any) + const [tempPayload, setTempPayload] = useState(() => payload || getNewVarInWorkflow('') as any) const { type, label, variable, options, max_length } = tempPayload const modalRef = useRef(null) const appDetail = useAppStore(state => state.appDetail) diff --git a/web/app/components/app/configuration/hooks/use-advanced-prompt-config.ts b/web/app/components/app/configuration/hooks/use-advanced-prompt-config.ts index 193ac87dd0..92958cc96d 100644 --- a/web/app/components/app/configuration/hooks/use-advanced-prompt-config.ts +++ b/web/app/components/app/configuration/hooks/use-advanced-prompt-config.ts @@ -35,8 +35,8 @@ const useAdvancedPromptConfig = ({ setStop, }: Param) => { const isAdvancedPrompt = promptMode === PromptMode.advanced - const [chatPromptConfig, setChatPromptConfig] = useState(clone(DEFAULT_CHAT_PROMPT_CONFIG)) - const [completionPromptConfig, setCompletionPromptConfig] = useState(clone(DEFAULT_COMPLETION_PROMPT_CONFIG)) + const [chatPromptConfig, setChatPromptConfig] = useState(() => clone(DEFAULT_CHAT_PROMPT_CONFIG)) + const [completionPromptConfig, setCompletionPromptConfig] = useState(() => clone(DEFAULT_COMPLETION_PROMPT_CONFIG)) const currentAdvancedPrompt = (() => { if (!isAdvancedPrompt) diff --git a/web/app/components/base/date-and-time-picker/date-picker/index.tsx b/web/app/components/base/date-and-time-picker/date-picker/index.tsx index f6b7973cb0..8653c6772d 100644 --- a/web/app/components/base/date-and-time-picker/date-picker/index.tsx +++ b/web/app/components/base/date-and-time-picker/date-picker/index.tsx @@ -55,8 +55,8 @@ const DatePicker = ({ const [currentDate, setCurrentDate] = useState(inputValue || defaultValue) const [selectedDate, setSelectedDate] = useState(inputValue) - const [selectedMonth, setSelectedMonth] = useState((inputValue || defaultValue).month()) - const [selectedYear, setSelectedYear] = useState((inputValue || defaultValue).year()) + const [selectedMonth, setSelectedMonth] = useState(() => (inputValue || defaultValue).month()) + const [selectedYear, setSelectedYear] = useState(() => (inputValue || defaultValue).year()) useEffect(() => { const handleClickOutside = (event: MouseEvent) => { diff --git a/web/app/components/base/date-and-time-picker/time-picker/index.tsx b/web/app/components/base/date-and-time-picker/time-picker/index.tsx index 8ef10abc2e..1fb2cfed11 100644 --- a/web/app/components/base/date-and-time-picker/time-picker/index.tsx +++ b/web/app/components/base/date-and-time-picker/time-picker/index.tsx @@ -28,7 +28,7 @@ const TimePicker = ({ const [isOpen, setIsOpen] = useState(false) const containerRef = useRef(null) const isInitial = useRef(true) - const [selectedTime, setSelectedTime] = useState(value ? getDateWithTimezone({ timezone, date: value }) : undefined) + const [selectedTime, setSelectedTime] = useState(() => value ? getDateWithTimezone({ timezone, date: value }) : undefined) useEffect(() => { const handleClickOutside = (event: MouseEvent) => { diff --git a/web/app/components/base/markdown-blocks/think-block.tsx b/web/app/components/base/markdown-blocks/think-block.tsx index acceecd433..a3b0561677 100644 --- a/web/app/components/base/markdown-blocks/think-block.tsx +++ b/web/app/components/base/markdown-blocks/think-block.tsx @@ -37,7 +37,7 @@ const removeEndThink = (children: any): any => { const useThinkTimer = (children: any) => { const { isResponding } = useChatContext() - const [startTime] = useState(Date.now()) + const [startTime] = useState(() => Date.now()) const [elapsedTime, setElapsedTime] = useState(0) const [isComplete, setIsComplete] = useState(false) const timerRef = useRef() diff --git a/web/app/components/base/notion-page-selector/base.tsx b/web/app/components/base/notion-page-selector/base.tsx index 1c54b57a18..adf044c406 100644 --- a/web/app/components/base/notion-page-selector/base.tsx +++ b/web/app/components/base/notion-page-selector/base.tsx @@ -93,7 +93,7 @@ const NotionPageSelector = ({ const defaultSelectedPagesId = useMemo(() => { return [...Array.from(pagesMapAndSelectedPagesId[1]), ...(value || [])] }, [pagesMapAndSelectedPagesId, value]) - const [selectedPagesId, setSelectedPagesId] = useState>(new Set(defaultSelectedPagesId)) + const [selectedPagesId, setSelectedPagesId] = useState>(() => new Set(defaultSelectedPagesId)) useEffect(() => { setSelectedPagesId(new Set(defaultSelectedPagesId)) diff --git a/web/app/components/base/tab-slider/index.tsx b/web/app/components/base/tab-slider/index.tsx index 56cde52154..55c44d5ea8 100644 --- a/web/app/components/base/tab-slider/index.tsx +++ b/web/app/components/base/tab-slider/index.tsx @@ -21,7 +21,7 @@ const TabSlider: FC = ({ onChange, options, }) => { - const [activeIndex, setActiveIndex] = useState(options.findIndex(option => option.value === value)) + const [activeIndex, setActiveIndex] = useState(() => options.findIndex(option => option.value === value)) const [sliderStyle, setSliderStyle] = useState({}) const { data: pluginList } = useInstalledPluginList() diff --git a/web/app/components/custom/custom-web-app-brand/index.tsx b/web/app/components/custom/custom-web-app-brand/index.tsx index ea2f44caea..eb06265042 100644 --- a/web/app/components/custom/custom-web-app-brand/index.tsx +++ b/web/app/components/custom/custom-web-app-brand/index.tsx @@ -38,7 +38,7 @@ const CustomWebAppBrand = () => { isCurrentWorkspaceManager, } = useAppContext() const [fileId, setFileId] = useState('') - const [imgKey, setImgKey] = useState(Date.now()) + const [imgKey, setImgKey] = useState(() => Date.now()) const [uploadProgress, setUploadProgress] = useState(0) const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) const isSandbox = enableBilling && plan.type === Plan.sandbox diff --git a/web/app/components/header/maintenance-notice.tsx b/web/app/components/header/maintenance-notice.tsx index 4bb4ef7f7d..bcbb344b2c 100644 --- a/web/app/components/header/maintenance-notice.tsx +++ b/web/app/components/header/maintenance-notice.tsx @@ -6,7 +6,7 @@ import { useLanguage } from '@/app/components/header/account-setting/model-provi const MaintenanceNotice = () => { const locale = useLanguage() - const [showNotice, setShowNotice] = useState(localStorage.getItem('hide-maintenance-notice') !== '1') + const [showNotice, setShowNotice] = useState(() => localStorage.getItem('hide-maintenance-notice') !== '1') const handleJumpNotice = () => { window.open(NOTICE_I18N.href, '_blank') } diff --git a/web/app/components/signin/countdown.tsx b/web/app/components/signin/countdown.tsx index 5fd6a29712..c16bd46fe4 100644 --- a/web/app/components/signin/countdown.tsx +++ b/web/app/components/signin/countdown.tsx @@ -12,7 +12,7 @@ type CountdownProps = { export default function Countdown({ onResend }: CountdownProps) { const { t } = useTranslation() - const [leftTime, setLeftTime] = useState(Number(localStorage.getItem(COUNT_DOWN_KEY) || COUNT_DOWN_TIME_MS)) + const [leftTime, setLeftTime] = useState(() => Number(localStorage.getItem(COUNT_DOWN_KEY) || COUNT_DOWN_TIME_MS)) const [time] = useCountDown({ leftTime, onEnd: () => { diff --git a/web/app/components/tools/mcp/modal.tsx b/web/app/components/tools/mcp/modal.tsx index 211d594caf..1a12b3b3e9 100644 --- a/web/app/components/tools/mcp/modal.tsx +++ b/web/app/components/tools/mcp/modal.tsx @@ -65,7 +65,7 @@ const MCPModal = ({ const originalServerID = data?.server_identifier const [url, setUrl] = React.useState(data?.server_url || '') const [name, setName] = React.useState(data?.name || '') - const [appIcon, setAppIcon] = useState(getIcon(data)) + const [appIcon, setAppIcon] = useState(() => getIcon(data)) const [showAppIconPicker, setShowAppIconPicker] = useState(false) const [serverIdentifier, setServerIdentifier] = React.useState(data?.server_identifier || '') const [timeout, setMcpTimeout] = React.useState(data?.timeout || 30) diff --git a/web/app/components/workflow/nodes/_base/hooks/use-resize-panel.ts b/web/app/components/workflow/nodes/_base/hooks/use-resize-panel.ts index f2259a02cf..336c440d58 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-resize-panel.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-resize-panel.ts @@ -33,7 +33,7 @@ export const useResizePanel = (params?: UseResizePanelParams) => { const initContainerWidthRef = useRef(0) const initContainerHeightRef = useRef(0) const isResizingRef = useRef(false) - const [prevUserSelectStyle, setPrevUserSelectStyle] = useState(getComputedStyle(document.body).userSelect) + const [prevUserSelectStyle, setPrevUserSelectStyle] = useState(() => getComputedStyle(document.body).userSelect) const handleStartResize = useCallback((e: MouseEvent) => { initXRef.current = e.clientX diff --git a/web/app/components/workflow/nodes/http/hooks/use-key-value-list.ts b/web/app/components/workflow/nodes/http/hooks/use-key-value-list.ts index a61cad646f..44774074dc 100644 --- a/web/app/components/workflow/nodes/http/hooks/use-key-value-list.ts +++ b/web/app/components/workflow/nodes/http/hooks/use-key-value-list.ts @@ -16,7 +16,7 @@ const strToKeyValueList = (value: string) => { } const useKeyValueList = (value: string, onChange: (value: string) => void, noFilter?: boolean) => { - const [list, doSetList] = useState(value ? strToKeyValueList(value) : []) + const [list, doSetList] = useState(() => value ? strToKeyValueList(value) : []) const setList = (l: KeyValue[]) => { doSetList(l.map((item) => { return { diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx index b87dc6e245..7c343d320a 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx @@ -55,7 +55,7 @@ const JsonSchemaConfig: FC = ({ const docLink = useDocLink() const [currentTab, setCurrentTab] = useState(SchemaView.VisualEditor) const [jsonSchema, setJsonSchema] = useState(defaultSchema || DEFAULT_SCHEMA) - const [json, setJson] = useState(JSON.stringify(jsonSchema, null, 2)) + const [json, setJson] = useState(() => JSON.stringify(jsonSchema, null, 2)) const [btnWidth, setBtnWidth] = useState(0) const [parseError, setParseError] = useState(null) const [validationError, setValidationError] = useState('') diff --git a/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx b/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx index 478ac925d6..8e6865f557 100644 --- a/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx +++ b/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx @@ -34,7 +34,7 @@ const ClassItem: FC = ({ filterVar, }) => { const { t } = useTranslation() - const [instanceId, setInstanceId] = useState(uniqueId()) + const [instanceId, setInstanceId] = useState(() => uniqueId()) useEffect(() => { setInstanceId(`${nodeId}-${uniqueId()}`) diff --git a/web/app/components/workflow/variable-inspect/value-content.tsx b/web/app/components/workflow/variable-inspect/value-content.tsx index 6c727e8699..47546a863e 100644 --- a/web/app/components/workflow/variable-inspect/value-content.tsx +++ b/web/app/components/workflow/variable-inspect/value-content.tsx @@ -69,7 +69,7 @@ const ValueContent = ({ const [json, setJson] = useState('') const [parseError, setParseError] = useState(null) const [validationError, setValidationError] = useState('') - const [fileValue, setFileValue] = useState(formatFileValue(currentVar)) + const [fileValue, setFileValue] = useState(() => formatFileValue(currentVar)) const { run: debounceValueChange } = useDebounceFn(handleValueChange, { wait: 500 }) diff --git a/web/app/components/workflow/workflow-preview/index.tsx b/web/app/components/workflow/workflow-preview/index.tsx index 2aeb09cd1e..5fd4b9097c 100644 --- a/web/app/components/workflow/workflow-preview/index.tsx +++ b/web/app/components/workflow/workflow-preview/index.tsx @@ -68,8 +68,8 @@ const WorkflowPreview = ({ viewport, className, }: WorkflowPreviewProps) => { - const [nodesData, setNodesData] = useState(initialNodes(nodes, edges)) - const [edgesData, setEdgesData] = useState(initialEdges(edges, nodes)) + const [nodesData, setNodesData] = useState(() => initialNodes(nodes, edges)) + const [edgesData, setEdgesData] = useState(() => initialEdges(edges, nodes)) const onNodesChange = useCallback( (changes: NodeChange[]) => setNodesData(nds => applyNodeChanges(changes, nds)), diff --git a/web/app/signin/invite-settings/page.tsx b/web/app/signin/invite-settings/page.tsx index 036edfc478..cec51a70ef 100644 --- a/web/app/signin/invite-settings/page.tsx +++ b/web/app/signin/invite-settings/page.tsx @@ -30,7 +30,7 @@ export default function InviteSettingsPage() { const { setLocaleOnClient } = useContext(I18n) const [name, setName] = useState('') const [language, setLanguage] = useState(LanguagesSupported[0]) - const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone || 'America/Los_Angeles') + const [timezone, setTimezone] = useState(() => Intl.DateTimeFormat().resolvedOptions().timeZone || 'America/Los_Angeles') const checkParams = { url: '/activate/check',