iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
佛心分享-SideProject30

就決定是你了!打造寶可夢持有追蹤系統 (React x Express)系列 第 26

DAY 26:實作前端簡易搜尋與過濾功能 (找出特定的寶可夢)

  • 分享至 

  • xImage
  •  

今日目標說明

當圖鑑或交換列表的資料變多時,除了滑動順暢,更重要的是「找得快」。今天我們要在畫面上加上搜尋框與過濾條件 (例如:過濾性別、地區、特定標籤),讓使用者能精準定位寶可夢!

【架構決策對比】Frontend Filtering vs Backend Filtering

在實作過濾功能時,我們通常面臨兩種選擇:

過濾策略 運作方式 優劣勢與適用情境
前端過濾 (Frontend Filtering) 先把資料庫「所有」資料一次抓回前端,再用 JS 的 array.filter() 在瀏覽器端做篩選。 優點:過濾極快,不需重打 API。缺點:如果資料有幾十萬筆,初次載入會非常慢,且耗費手機記憶體。適用:總資料量小於一千筆的系統。
後端過濾 (Backend Filtering) 前端將搜尋關鍵字傳給後端,由後端的 SQL (WHERE name LIKE '%皮卡丘%') 執行過濾後,只回傳需要的資料。 優點:前端永遠只收到必要的輕量資料,節省頻寬與記憶體。缺點:每次打字過濾都要送 API 請求 (通常需搭配 Debounce 防抖)。適用:大型資料庫、企業級系統 (本專案採用此架構的變體設計)。

在我們的系統中,由於搭配了 React Query 的強大快取,我們把過濾條件交給 Hook 統一管理,完美結合了後端查詢與前端快取的優勢。

核心程式碼片段

我們設計了一個 useFilters 來管理使用者的搜尋條件,並將這些條件無縫傳遞給 React Query:

import { useState, useMemo } from 'react';
import { TextField, Box } from '@mui/material';

// 假設這是在圖鑑頁面 (PokedexPage.tsx)
const PokedexPage = () => {
  // 1. 統一管理所有過濾狀態
  const { filters, updateFilter } = useFilters();
  
  // 2. 將過濾條件餵給 React Query
  // 當 filters 改變時,queryKey 也會變,自動觸發背景 API 重新抓取或從快取拿資料!
  const { data, isLoading } = useDetailedPokemon(filters);

  return (
    <Box>
      {/* 搜尋框:輸入文字即時更新 filter 狀態 */}
      <TextField 
        placeholder="搜尋寶可夢名稱或編號..."
        value={filters.searchText || ''}
        onChange={(e) => updateFilter('searchText', e.target.value)}
        fullWidth
        sx={{ mb: 2 }}
      />
      
      {/* 渲染過濾後的資料列表 */}
      {isLoading ? <div>搜尋中...</div> : (
        <div>共找到 {data?.pages[0]?.total} 筆符合條件的寶可夢!</div>
      )}
    </Box>
  );
};

實際畫面截圖

搜尋與過濾功能

輸入框搜尋「伊布」,下方立刻過濾出對應的寶可夢!

小結

結合 React Window 帶來了順暢的滾動,結合 React Query 與 Filters 帶來了極速的搜尋,前端的「進階功能與效能優化 (階段四)」正式完成!鐵人賽即將進入最後衝刺,明天我們要邁入階段五:將心血結晶部署上雲端!


上一篇
DAY 25:實作 React Window 虛擬滾動列表 (核心程式碼對比)
下一篇
DAY 27:後端部署:將 Express 專案放上 Vercel (無伺服器部署)
系列文
就決定是你了!打造寶可夢持有追蹤系統 (React x Express)30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言