From f36a29baec9dff59f6f5c89dadbad5d31f22eebc Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Tue, 18 Mar 2025 15:18:57 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=B3=A8=E9=87=8A=20react-hooks/ex?= =?UTF-8?q?haustive-deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/src/hooks/resource.ts | 5 +- react-ui/src/pages/Authorize/index.tsx | 35 ++-- react-ui/src/pages/AutoML/Instance/index.tsx | 4 +- react-ui/src/pages/Experiment/Info/index.jsx | 18 +- .../Experiment/components/LogGroup/index.tsx | 160 ++++++++++-------- .../pages/HyperParameter/Instance/index.tsx | 10 +- .../Model/components/ModelEvolution/index.tsx | 4 + react-ui/src/pages/Monitor/JobLog/index.tsx | 2 +- react-ui/src/pages/Pipeline/Info/index.jsx | 3 + .../Pipeline/components/ModelMenu/index.tsx | 63 ++++--- .../pages/System/User/components/DeptTree.tsx | 46 ++--- react-ui/src/pages/Tool/Gen/edit.tsx | 3 +- 12 files changed, 190 insertions(+), 163 deletions(-) diff --git a/react-ui/src/hooks/resource.ts b/react-ui/src/hooks/resource.ts index cb4434ab..6331edab 100644 --- a/react-ui/src/hooks/resource.ts +++ b/react-ui/src/hooks/resource.ts @@ -49,7 +49,10 @@ export function useComputingResource() { // 根据 standard 获取 description const getDescription = useCallback( - (standard: string) => { + (standard?: string) => { + if (!standard) { + return undefined; + } return resourceStandardList.find((item) => item.standard === standard)?.description; }, [resourceStandardList], diff --git a/react-ui/src/pages/Authorize/index.tsx b/react-ui/src/pages/Authorize/index.tsx index e42a0f1b..2caf3195 100644 --- a/react-ui/src/pages/Authorize/index.tsx +++ b/react-ui/src/pages/Authorize/index.tsx @@ -3,7 +3,7 @@ import { loginByOauth2Req } from '@/services/auth'; import { to } from '@/utils/promise'; import { history, useModel, useSearchParams } from '@umijs/max'; import { message } from 'antd'; -import { useEffect } from 'react'; +import { useCallback, useEffect } from 'react'; import { flushSync } from 'react-dom'; import styles from './index.less'; @@ -12,12 +12,21 @@ function Authorize() { const [searchParams] = useSearchParams(); const code = searchParams.get('code'); const redirect = searchParams.get('redirect'); - useEffect(() => { - loginByOauth2(); - }, []); + + const fetchUserInfo = useCallback(async () => { + const userInfo = await initialState?.fetchUserInfo?.(); + if (userInfo) { + flushSync(() => { + setInitialState((s) => ({ + ...s, + currentUser: userInfo, + })); + }); + } + }, [initialState, setInitialState]); // 登录 - const loginByOauth2 = async () => { + const loginByOauth2 = useCallback(async () => { const params = { code, }; @@ -29,19 +38,11 @@ function Authorize() { await fetchUserInfo(); history.push(redirect || '/'); } - }; + }, [fetchUserInfo, redirect, code]); - const fetchUserInfo = async () => { - const userInfo = await initialState?.fetchUserInfo?.(); - if (userInfo) { - flushSync(() => { - setInitialState((s) => ({ - ...s, - currentUser: userInfo, - })); - }); - } - }; + useEffect(() => { + loginByOauth2(); + }, [loginByOauth2]); return
; } diff --git a/react-ui/src/pages/AutoML/Instance/index.tsx b/react-ui/src/pages/AutoML/Instance/index.tsx index 8b525bdd..2dead784 100644 --- a/react-ui/src/pages/AutoML/Instance/index.tsx +++ b/react-ui/src/pages/AutoML/Instance/index.tsx @@ -39,6 +39,7 @@ function AutoMLInstance() { return () => { closeSSE(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // 获取实验实例详情 @@ -83,9 +84,6 @@ function AutoMLInstance() { const setupSSE = (name: string, namespace: string) => { const { origin } = location; - // if (process.env.NODE_ENV === 'development') { - // origin = 'http://172.20.32.197:31213'; - // } const params = encodeURIComponent(`metadata.namespace=${namespace},metadata.name=${name}`); const evtSource = new EventSource( `${origin}/api/v1/realtimeStatus?listOptions.fieldSelector=${params}`, diff --git a/react-ui/src/pages/Experiment/Info/index.jsx b/react-ui/src/pages/Experiment/Info/index.jsx index e05480df..f0cf9ae6 100644 --- a/react-ui/src/pages/Experiment/Info/index.jsx +++ b/react-ui/src/pages/Experiment/Info/index.jsx @@ -21,7 +21,6 @@ function ExperimentText() { const [experimentIns, setExperimentIns] = useState(undefined); const [experimentNodeData, setExperimentNodeData, experimentNodeDataRef] = useStateRef(undefined); const graphRef = useRef(); - const timerRef = useRef(); const workflowRef = useRef(); const locationParams = useParams(); // 新版本获取路由参数接口 const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false); @@ -36,6 +35,16 @@ function ExperimentText() { initGraph(); getWorkflow(); + return () => { + if (evtSourceRef.current) { + evtSourceRef.current.close(); + evtSourceRef.current = null; + } + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { const changeSize = () => { if (!graph || graph.get('destroyed')) return; if (!graphRef.current) return; @@ -46,13 +55,6 @@ function ExperimentText() { window.addEventListener('resize', changeSize); return () => { window.removeEventListener('resize', changeSize); - if (timerRef.current) { - clearTimeout(timerRef.current); - } - if (evtSourceRef.current) { - evtSourceRef.current.close(); - evtSourceRef.current = null; - } }; }, []); diff --git a/react-ui/src/pages/Experiment/components/LogGroup/index.tsx b/react-ui/src/pages/Experiment/components/LogGroup/index.tsx index dfedac5c..e69b4773 100644 --- a/react-ui/src/pages/Experiment/components/LogGroup/index.tsx +++ b/react-ui/src/pages/Experiment/components/LogGroup/index.tsx @@ -46,12 +46,94 @@ function LogGroup({ setHasRun(true); } + // 进入页面时,滚动到底部 useEffect(() => { + scrollToBottom(false); + }, []); + + useEffect(() => { + // 建立 socket 连接 + const setupSockect = () => { + let { host } = location; + if (process.env.NODE_ENV === 'development') { + host = '172.20.32.197:31213'; + } + const socket = new WebSocket( + `ws://${host}/newlog/realtimeLog?start=${start_time}&query={pod="${pod_name}"}`, + ); + + socket.addEventListener('open', () => { + console.log('WebSocket is open now.'); + }); + + socket.addEventListener('close', (event) => { + console.log('WebSocket is closed:', event); + // 有时候会出现连接失败,重试 3 次 + if (event.code !== 1000 && retryRef.current > 0) { + retryRef.current -= 1; + setTimeout(() => { + setupSockect(); + }, 2 * 1000); + } + }); + + socket.addEventListener('error', (event) => { + console.error('WebSocket error observed:', event); + }); + + socket.addEventListener('message', (event) => { + // console.log('message received.', event); + if (!event.data) { + return; + } + try { + const data = JSON.parse(event.data); + const streams = data.streams; + if (!streams || !Array.isArray(streams)) { + return; + } + let startTime = start_time; + const logContent = streams.reduce((result, item) => { + const values = item.values; + return ( + result + + values.reduce((prev: string, cur: [string, string]) => { + const [time, value] = cur; + startTime = time; + const str = `[${dayjs(Number(time) / 1.0e6).format( + 'YYYY-MM-DD HH:mm:ss', + )}] ${value}`; + return prev + str; + }, '') + ); + }, ''); + const logDetail: Log = { + start_time: startTime!, + log_content: logContent, + pod_name: pod_name, + }; + setLogList((oldList) => oldList.concat(logDetail)); + if (!isMouseDownRef.current && logContent) { + setTimeout(() => { + scrollToBottom(); + }, 100); + } + } catch (error) { + console.error('JSON parse error: ', error); + } + }); + + socketRef.current = socket; + }; + if (status === ExperimentStatus.Running) { setupSockect(); } - scrollToBottom(false); - }, [status]); + + return () => { + closeSocket(); + }; + }, [status, start_time, pod_name, isMouseDownRef, setLogList]); // 鼠标拖到中不滚动到底部 useEffect(() => { @@ -66,7 +148,6 @@ function LogGroup({ return () => { document.removeEventListener('mousedown', mouseDown); document.removeEventListener('mouseup', mouseUp); - closeSocket(); }; }, [setIsMouseDown]); @@ -120,78 +201,7 @@ function LogGroup({ requestExperimentPodsLog(); }; - // 建立 socket 连接 - const setupSockect = () => { - let { host } = location; - if (process.env.NODE_ENV === 'development') { - host = '172.20.32.197:31213'; - } - const socket = new WebSocket( - `ws://${host}/newlog/realtimeLog?start=${start_time}&query={pod="${pod_name}"}`, - ); - - socket.addEventListener('open', () => { - console.log('WebSocket is open now.'); - }); - - socket.addEventListener('close', (event) => { - console.log('WebSocket is closed:', event); - // 有时候会出现连接失败,重试 3 次 - if (event.code !== 1000 && retryRef.current > 0) { - retryRef.current -= 1; - setTimeout(() => { - setupSockect(); - }, 2 * 1000); - } - }); - - socket.addEventListener('error', (event) => { - console.error('WebSocket error observed:', event); - }); - - socket.addEventListener('message', (event) => { - // console.log('message received.', event); - if (!event.data) { - return; - } - try { - const data = JSON.parse(event.data); - const streams = data.streams; - if (!streams || !Array.isArray(streams)) { - return; - } - let startTime = start_time; - const logContent = streams.reduce((result, item) => { - const values = item.values; - return ( - result + - values.reduce((prev: string, cur: [string, string]) => { - const [time, value] = cur; - startTime = time; - const str = `[${dayjs(Number(time) / 1.0e6).format('YYYY-MM-DD HH:mm:ss')}] ${value}`; - return prev + str; - }, '') - ); - }, ''); - const logDetail: Log = { - start_time: startTime!, - log_content: logContent, - pod_name: pod_name, - }; - setLogList((oldList) => oldList.concat(logDetail)); - if (!isMouseDownRef.current && logContent) { - setTimeout(() => { - scrollToBottom(); - }, 100); - } - } catch (error) { - console.error('JSON parse error: ', error); - } - }); - - socketRef.current = socket; - }; - + // 关闭 socket const closeSocket = () => { if (socketRef.current) { socketRef.current.close(1000, 'completed'); diff --git a/react-ui/src/pages/HyperParameter/Instance/index.tsx b/react-ui/src/pages/HyperParameter/Instance/index.tsx index aa206059..5e4c5ab7 100644 --- a/react-ui/src/pages/HyperParameter/Instance/index.tsx +++ b/react-ui/src/pages/HyperParameter/Instance/index.tsx @@ -22,6 +22,8 @@ enum TabKeys { History = 'history', } +const NodePrefix = 'workflow'; + function HyperParameterInstance() { const [experimentInfo, setExperimentInfo] = useState(undefined); const [instanceInfo, setInstanceInfo] = useState( @@ -41,6 +43,7 @@ function HyperParameterInstance() { return () => { closeSSE(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // 获取实验实例详情 @@ -83,7 +86,7 @@ function HyperParameterInstance() { if (nodeStatusJson) { setNodes(nodeStatusJson); Object.keys(nodeStatusJson).some((key) => { - if (key.startsWith('workflow')) { + if (key.startsWith(NodePrefix)) { const workflowStatus = nodeStatusJson[key]; setWorkflowStatus(workflowStatus); return true; @@ -101,9 +104,6 @@ function HyperParameterInstance() { const setupSSE = (name: string, namespace: string) => { const { origin } = location; - // if (process.env.NODE_ENV === 'development') { - // origin = 'http://172.20.32.197:31213'; - // } const params = encodeURIComponent(`metadata.namespace=${namespace},metadata.name=${name}`); const evtSource = new EventSource( `${origin}/api/v1/realtimeStatus?listOptions.fieldSelector=${params}`, @@ -119,7 +119,7 @@ function HyperParameterInstance() { const nodes = dataJson?.result?.object?.status?.nodes; if (nodes) { const workflowStatus = Object.values(nodes).find((node: any) => - node.displayName.startsWith('workflow'), + node.displayName.startsWith(NodePrefix), ) as NodeStatus; // 节点 diff --git a/react-ui/src/pages/Model/components/ModelEvolution/index.tsx b/react-ui/src/pages/Model/components/ModelEvolution/index.tsx index 0f02ead6..42b85f21 100644 --- a/react-ui/src/pages/Model/components/ModelEvolution/index.tsx +++ b/react-ui/src/pages/Model/components/ModelEvolution/index.tsx @@ -56,6 +56,10 @@ function ModelEvolution({ useEffect(() => { initGraph(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { const changeSize = () => { if (!graph || graph.get('destroyed')) return; if (!graphRef.current) return; diff --git a/react-ui/src/pages/Monitor/JobLog/index.tsx b/react-ui/src/pages/Monitor/JobLog/index.tsx index 4c69330a..9af85b9c 100644 --- a/react-ui/src/pages/Monitor/JobLog/index.tsx +++ b/react-ui/src/pages/Monitor/JobLog/index.tsx @@ -124,7 +124,7 @@ const JobLogTableList: React.FC = () => { getDictValueEnum('sys_job_group').then((data) => { setJobGroupOptions(data); }); - }, []); + }, [jobId]); const columns: ProColumns[] = [ { diff --git a/react-ui/src/pages/Pipeline/Info/index.jsx b/react-ui/src/pages/Pipeline/Info/index.jsx index 74760f4d..353ef7e0 100644 --- a/react-ui/src/pages/Pipeline/Info/index.jsx +++ b/react-ui/src/pages/Pipeline/Info/index.jsx @@ -32,7 +32,10 @@ const EditPipeline = () => { useEffect(() => { initGraph(); getFirstWorkflow(locationParams.id); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { const changeSize = () => { if (!graph || graph.get('destroyed')) return; if (!graphRef.current) return; diff --git a/react-ui/src/pages/Pipeline/components/ModelMenu/index.tsx b/react-ui/src/pages/Pipeline/components/ModelMenu/index.tsx index 2224192c..8b420fff 100644 --- a/react-ui/src/pages/Pipeline/components/ModelMenu/index.tsx +++ b/react-ui/src/pages/Pipeline/components/ModelMenu/index.tsx @@ -1,7 +1,7 @@ import { getComponentAll } from '@/services/pipeline/index.js'; import { PipelineNodeModel } from '@/types'; import { to } from '@/utils/promise'; -import { Collapse, type CollapseProps } from 'antd'; +import { Collapse } from 'antd'; import { useEffect, useState } from 'react'; import Styles from './index.less'; @@ -18,7 +18,6 @@ type ModelMenuProps = { }; const ModelMenu = ({ onComponentDragEnd }: ModelMenuProps) => { const [modelMenusList, setModelMenusList] = useState([]); - const [collapseItems, setCollapseItems] = useState([]); useEffect(() => { // 获取所有组件 @@ -27,35 +26,6 @@ const ModelMenu = ({ onComponentDragEnd }: ModelMenuProps) => { if (res && res.data) { const menus = res.data as ModelMenuData[]; setModelMenusList(menus); - const items = menus.map((item) => { - return { - key: item.key, - label: item.name, - children: item.value.map((ele) => { - return ( -
{ - dragEnd(e, ele); - }} - className={Styles.collapseItem} - > - {ele.icon_path && ( - - )} - {ele.component_label} -
- ); - }), - }; - }); - setCollapseItems(items); } }; @@ -73,6 +43,35 @@ const ModelMenu = ({ onComponentDragEnd }: ModelMenuProps) => { }; const defaultActiveKey = modelMenusList.map((item) => item.key + ''); + const items = modelMenusList.map((item) => { + return { + key: item.key, + label: item.name, + children: item.value.map((ele) => { + return ( +
{ + dragEnd(e, ele); + }} + className={Styles.collapseItem} + > + {ele.icon_path && ( + + )} + {ele.component_label} +
+ ); + }), + }; + }); + return (
组件库
@@ -82,7 +81,7 @@ const ModelMenu = ({ onComponentDragEnd }: ModelMenuProps) => { collapsible="header" expandIconPosition="end" defaultActiveKey={defaultActiveKey} - items={collapseItems} + items={items} > ) : null}
diff --git a/react-ui/src/pages/System/User/components/DeptTree.tsx b/react-ui/src/pages/System/User/components/DeptTree.tsx index f839651c..395cf7a0 100644 --- a/react-ui/src/pages/System/User/components/DeptTree.tsx +++ b/react-ui/src/pages/System/User/components/DeptTree.tsx @@ -19,31 +19,37 @@ const DeptTree: React.FC = (props) => { const [treeData, setTreeData] = useState([]); const [expandedKeys, setExpandedKeys] = useState([]); const [selectedKeys, setSelectedKeys] = useState([]); - - const fetchDeptList = async () => { - const hide = message.loading('正在查询'); - try { - const res = await getDeptTree({}); - const treeData = res.map((item: any) => ({ ...item, key: item.id })); - setTreeData(treeData); - props.onSelect(treeData[0]); - setExpandedKeys([treeData[0].key]); - setSelectedKeys([treeData[0].key]); - hide(); - return true; - } catch (error) { - hide(); - return false; - } - }; + const { onSelect } = props; useEffect(() => { + const fetchDeptList = async () => { + const hide = message.loading('正在查询'); + try { + const res = await getDeptTree({}); + const treeData = res.map((item: any) => ({ ...item, key: item.id })); + setTreeData(treeData); + setExpandedKeys([treeData[0].key]); + setSelectedKeys([treeData[0].key]); + hide(); + return true; + } catch (error) { + hide(); + return false; + } + }; + fetchDeptList(); }, []); - const onSelect = (keys: React.Key[], info: any) => { + useEffect(() => { + if (treeData.length > 0) { + onSelect(treeData[0]); + } + }, [treeData, onSelect]); + + const handleSelect = (keys: React.Key[], info: any) => { setSelectedKeys(keys); - props.onSelect(info.node); + onSelect(info.node); }; const onExpand = (keys: React.Key[]) => { @@ -57,7 +63,7 @@ const DeptTree: React.FC = (props) => { onExpand={onExpand} expandedKeys={expandedKeys} selectedKeys={selectedKeys} - onSelect={onSelect} + onSelect={handleSelect} treeData={treeData} /> ); diff --git a/react-ui/src/pages/Tool/Gen/edit.tsx b/react-ui/src/pages/Tool/Gen/edit.tsx index be4d7111..c38bac3b 100644 --- a/react-ui/src/pages/Tool/Gen/edit.tsx +++ b/react-ui/src/pages/Tool/Gen/edit.tsx @@ -114,6 +114,7 @@ const TableList: React.FC = () => { }; useEffect(() => { setStepComponent(getCurrentStepAndComponent(stepKey)); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [stepKey]); useEffect(() => { @@ -150,7 +151,7 @@ const TableList: React.FC = () => { message.error(res.msg); } }); - }, []); + }, [tableId]); // const onFinish = (values: any) => { // console.log('Success:', values);