From da738dddab8a22d9779ca612513ab3e1db00b14b Mon Sep 17 00:00:00 2001 From: yyh Date: Thu, 22 Jan 2026 16:19:35 +0800 Subject: [PATCH] refactor: extract sqlite table hook --- .../viewer/sqlite-file-preview/index.tsx | 78 +--------------- .../sqlite-file-preview/use-sqlite-table.ts | 92 +++++++++++++++++++ 2 files changed, 95 insertions(+), 75 deletions(-) create mode 100644 web/app/components/workflow/skill/viewer/sqlite-file-preview/use-sqlite-table.ts diff --git a/web/app/components/workflow/skill/viewer/sqlite-file-preview/index.tsx b/web/app/components/workflow/skill/viewer/sqlite-file-preview/index.tsx index cf110654cb..a87acc3860 100644 --- a/web/app/components/workflow/skill/viewer/sqlite-file-preview/index.tsx +++ b/web/app/components/workflow/skill/viewer/sqlite-file-preview/index.tsx @@ -1,11 +1,12 @@ import type { FC } from 'react' import * as React from 'react' -import { useEffect, useMemo, useReducer, useRef, useState } from 'react' +import { useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import Loading from '@/app/components/base/loading' import { useSQLiteDatabase } from '../../hooks/use-sqlite-database' import TablePanel from './table-panel' import TableSelector from './table-selector' +import { useSQLiteTable } from './use-sqlite-table' type SQLiteFilePreviewProps = { downloadUrl: string @@ -18,51 +19,6 @@ const SQLiteFilePreview: FC = ({ const { tables, isLoading, error, queryTable } = useSQLiteDatabase(downloadUrl) const [selectedTableId, setSelectedTableId] = useState('') const tableScrollRef = useRef(null) - const [tableState, dispatch] = useReducer(( - current: { - data: Awaited> | null - isLoading: boolean - error: Error | null - }, - action: - | { type: 'reset' } - | { type: 'loading' } - | { type: 'success', data: Awaited> | null } - | { type: 'error', error: Error }, - ) => { - switch (action.type) { - case 'reset': - return { - data: null, - isLoading: false, - error: null, - } - case 'loading': - return { - data: null, - isLoading: true, - error: null, - } - case 'success': - return { - data: action.data, - isLoading: false, - error: null, - } - case 'error': - return { - data: null, - isLoading: false, - error: action.error, - } - default: - return current - } - }, { - data: null, - isLoading: false, - error: null, - }) const selectedTable = useMemo(() => { if (tables.length === 0) @@ -71,35 +27,7 @@ const SQLiteFilePreview: FC = ({ return selectedTableId return tables[0] }, [selectedTableId, tables]) - - useEffect(() => { - if (!selectedTable) { - dispatch({ type: 'reset' }) - return - } - - let cancelled = false - - const loadTable = async () => { - dispatch({ type: 'loading' }) - - try { - const data = await queryTable(selectedTable) - if (!cancelled) - dispatch({ type: 'success', data }) - } - catch (err) { - if (!cancelled) - dispatch({ type: 'error', error: err instanceof Error ? err : new Error(String(err)) }) - } - } - - loadTable() - - return () => { - cancelled = true - } - }, [queryTable, selectedTable]) + const tableState = useSQLiteTable({ selectedTable, queryTable }) if (!downloadUrl) { return ( diff --git a/web/app/components/workflow/skill/viewer/sqlite-file-preview/use-sqlite-table.ts b/web/app/components/workflow/skill/viewer/sqlite-file-preview/use-sqlite-table.ts new file mode 100644 index 0000000000..c738ab458c --- /dev/null +++ b/web/app/components/workflow/skill/viewer/sqlite-file-preview/use-sqlite-table.ts @@ -0,0 +1,92 @@ +import type { SQLiteQueryResult } from '../../hooks/sqlite/types' +import { useEffect, useReducer } from 'react' + +type TableState = { + data: SQLiteQueryResult | null + isLoading: boolean + error: Error | null +} + +type TableAction + = | { type: 'reset' } + | { type: 'loading' } + | { type: 'success', data: SQLiteQueryResult | null } + | { type: 'error', error: Error } + +type UseSQLiteTableArgs = { + selectedTable: string + queryTable: (tableName: string, limit?: number) => Promise +} + +const initialTableState: TableState = { + data: null, + isLoading: false, + error: null, +} + +export const useSQLiteTable = ({ + selectedTable, + queryTable, +}: UseSQLiteTableArgs): TableState => { + const [tableState, dispatch] = useReducer((current: TableState, action: TableAction): TableState => { + switch (action.type) { + case 'reset': + return { + data: null, + isLoading: false, + error: null, + } + case 'loading': + return { + data: null, + isLoading: true, + error: null, + } + case 'success': + return { + data: action.data, + isLoading: false, + error: null, + } + case 'error': + return { + data: null, + isLoading: false, + error: action.error, + } + default: + return current + } + }, initialTableState) + + useEffect(() => { + if (!selectedTable) { + dispatch({ type: 'reset' }) + return + } + + let cancelled = false + + const loadTable = async () => { + dispatch({ type: 'loading' }) + + try { + const data = await queryTable(selectedTable) + if (!cancelled) + dispatch({ type: 'success', data }) + } + catch (err) { + if (!cancelled) + dispatch({ type: 'error', error: err instanceof Error ? err : new Error(String(err)) }) + } + } + + loadTable() + + return () => { + cancelled = true + } + }, [queryTable, selectedTable]) + + return tableState +}