refactor(web): migrate explore app lists from useSWR to TanStack Query (#30076)

This commit is contained in:
yyh
2025-12-24 17:03:43 +08:00
committed by GitHub
parent 1e3823e605
commit 18d69775ef
6 changed files with 91 additions and 81 deletions

View File

@ -10,7 +10,7 @@ import AppList from './index'
const allCategoriesEn = 'explore.apps.allCategories:{"lng":"en"}'
let mockTabValue = allCategoriesEn
const mockSetTab = vi.fn()
let mockSWRData: { categories: string[], allList: App[] } = { categories: [], allList: [] }
let mockExploreData: { categories: string[], allList: App[] } = { categories: [], allList: [] }
const mockHandleImportDSL = vi.fn()
const mockHandleImportDSLConfirm = vi.fn()
@ -33,9 +33,9 @@ vi.mock('ahooks', async () => {
}
})
vi.mock('swr', () => ({
__esModule: true,
default: () => ({ data: mockSWRData }),
vi.mock('@/service/use-explore', () => ({
exploreAppListInitialData: { categories: [], allList: [] },
useExploreAppList: () => ({ data: mockExploreData }),
}))
vi.mock('@/service/explore', () => ({
@ -135,14 +135,14 @@ describe('AppList', () => {
beforeEach(() => {
vi.clearAllMocks()
mockTabValue = allCategoriesEn
mockSWRData = { categories: [], allList: [] }
mockExploreData = { categories: [], allList: [] }
})
// Rendering: show loading when categories are not ready.
describe('Rendering', () => {
it('should render loading when categories are empty', () => {
// Arrange
mockSWRData = { categories: [], allList: [] }
mockExploreData = { categories: [], allList: [] }
// Act
renderWithContext()
@ -153,7 +153,7 @@ describe('AppList', () => {
it('should render app cards when data is available', () => {
// Arrange
mockSWRData = {
mockExploreData = {
categories: ['Writing', 'Translate'],
allList: [createApp(), createApp({ app_id: 'app-2', app: { ...createApp().app, name: 'Beta' }, category: 'Translate' })],
}
@ -172,7 +172,7 @@ describe('AppList', () => {
it('should filter apps by selected category', () => {
// Arrange
mockTabValue = 'Writing'
mockSWRData = {
mockExploreData = {
categories: ['Writing', 'Translate'],
allList: [createApp(), createApp({ app_id: 'app-2', app: { ...createApp().app, name: 'Beta' }, category: 'Translate' })],
}
@ -190,7 +190,7 @@ describe('AppList', () => {
describe('User Interactions', () => {
it('should filter apps by search keywords', async () => {
// Arrange
mockSWRData = {
mockExploreData = {
categories: ['Writing'],
allList: [createApp(), createApp({ app_id: 'app-2', app: { ...createApp().app, name: 'Gamma' } })],
}
@ -210,7 +210,7 @@ describe('AppList', () => {
it('should handle create flow and confirm DSL when pending', async () => {
// Arrange
const onSuccess = vi.fn()
mockSWRData = {
mockExploreData = {
categories: ['Writing'],
allList: [createApp()],
};
@ -246,7 +246,7 @@ describe('AppList', () => {
describe('Edge Cases', () => {
it('should reset search results when clear icon is clicked', async () => {
// Arrange
mockSWRData = {
mockExploreData = {
categories: ['Writing'],
allList: [createApp(), createApp({ app_id: 'app-2', app: { ...createApp().app, name: 'Gamma' } })],
}

View File

@ -6,7 +6,6 @@ import { useDebounceFn } from 'ahooks'
import * as React from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import useSWR from 'swr'
import { useContext } from 'use-context-selector'
import DSLConfirmModal from '@/app/components/app/create-from-dsl-modal/dsl-confirm-modal'
import Input from '@/app/components/base/input'
@ -20,7 +19,8 @@ import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
import {
DSLImportMode,
} from '@/models/app'
import { fetchAppDetail, fetchAppList } from '@/service/explore'
import { fetchAppDetail } from '@/service/explore'
import { exploreAppListInitialData, useExploreAppList } from '@/service/use-explore'
import { cn } from '@/utils/classnames'
import s from './style.module.css'
@ -58,21 +58,8 @@ const Apps = ({
})
const {
data: { categories, allList },
} = useSWR(
['/explore/apps'],
() =>
fetchAppList().then(({ categories, recommended_apps }) => ({
categories,
allList: recommended_apps.sort((a, b) => a.position - b.position),
})),
{
fallbackData: {
categories: [],
allList: [],
},
},
)
data: { categories, allList } = exploreAppListInitialData,
} = useExploreAppList()
const filteredList = allList.filter(item => currCategory === allCategoriesEn || item.category === currCategory)