refactor: extract sqlite table hook

This commit is contained in:
yyh
2026-01-22 16:19:35 +08:00
parent aa1ee123b3
commit da738dddab
2 changed files with 95 additions and 75 deletions

View File

@ -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<SQLiteFilePreviewProps> = ({
const { tables, isLoading, error, queryTable } = useSQLiteDatabase(downloadUrl)
const [selectedTableId, setSelectedTableId] = useState<string>('')
const tableScrollRef = useRef<HTMLDivElement | null>(null)
const [tableState, dispatch] = useReducer((
current: {
data: Awaited<ReturnType<typeof queryTable>> | null
isLoading: boolean
error: Error | null
},
action:
| { type: 'reset' }
| { type: 'loading' }
| { type: 'success', data: Awaited<ReturnType<typeof queryTable>> | 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<SQLiteFilePreviewProps> = ({
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 (

View File

@ -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<SQLiteQueryResult | null>
}
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
}