如何使用useContext实现搜索栏过滤功能 附基础实现代码参考
实现步骤
1. 调整全局上下文(GlobalState)逻辑
首先需要在全局状态中新增搜索关键词的存储和更新方法,确保搜索栏和PizzaList组件可以共享该状态,参考修改后的GlobalState.js代码:
import React, { createContext, useReducer } from 'react'; import pizzaReducer from './reducers/pizzaReducer'; // 替换为你原有reducer的实际路径 const initialState = { pizzas: [], searchKeyword: '', // 新增搜索关键词存储字段 }; export const GlobalContext = createContext(initialState); export const GlobalProvider = ({ children }) => { const [state, dispatch] = useReducer(pizzaReducer, initialState); // 原有获取披萨列表的逻辑保持不变 const getPizzas = async () => { // 此处保留你原有拉取数据的逻辑 }; // 新增更新搜索关键词的方法 const setSearchKeyword = (keyword) => { dispatch({ type: 'SET_SEARCH_KEYWORD', payload: keyword }); }; return ( <GlobalContext.Provider value={{ pizzas: state.pizzas, searchKeyword: state.searchKeyword, getPizzas, setSearchKeyword }}> {children} </GlobalContext.Provider> ); };
同步在对应的reducer中新增状态处理逻辑:
// pizzaReducer.js 新增对应处理分支 const pizzaReducer = (state, action) => { switch(action.type) { // 保留你原有的其他case逻辑 case 'SET_SEARCH_KEYWORD': return { ...state, searchKeyword: action.payload }; default: return state; } };
2. 实现搜索栏组件
可以单独抽离搜索栏组件提升复用性,也可以直接将搜索框写在PizzaList组件内:
// SearchBar.js import React, { useContext } from 'react'; import { GlobalContext } from '../context/GlobalState'; export const SearchBar = () => { const { searchKeyword, setSearchKeyword } = useContext(GlobalContext); return ( <div className="search-bar"> <input type="text" placeholder="搜索披萨名称、配料..." value={searchKeyword} onChange={(e) => setSearchKeyword(e.target.value)} /> </div> ); };
3. 改造PizzaList组件新增过滤逻辑
在渲染列表前先根据搜索关键词过滤数据,这里默认按披萨名称做模糊匹配,你可以根据业务需求调整匹配字段(比如配料、描述等):
import React, { useContext, useEffect, useMemo } from "react"; import { Pizza } from "./Pizza"; import { SearchBar } from "./SearchBar"; // 引入搜索栏组件 import { GlobalContext } from "../context/GlobalState"; export const PizzaList = () => { const { pizzas, getPizzas, searchKeyword } = useContext(GlobalContext); useEffect(() => { getPizzas(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // 用useMemo缓存过滤结果,仅当披萨列表或搜索关键词变化时才重新计算 const filteredPizzas = useMemo(() => { // 搜索关键词为空时返回全量数据 if (!searchKeyword.trim()) return pizzas; const lowerKeyword = searchKeyword.toLowerCase(); return pizzas.filter(pizza => // 可自行扩展匹配规则,比如匹配配料 pizza.ingredients.some(item => item.toLowerCase().includes(lowerKeyword)) pizza.name.toLowerCase().includes(lowerKeyword) ); }, [pizzas, searchKeyword]); return ( <> <SearchBar /> {/* 渲染搜索栏 */} <h3>History</h3> <ul className="list"> {filteredPizzas.map((pizza) => ( <Pizza key={pizza.id} pizza={pizza} /> ))} {/* 可选:新增无匹配结果的提示 */} {filteredPizzas.length === 0 && searchKeyword.trim() && ( <li className="no-result">没有找到匹配的披萨</li> )} </ul> </> ); };
补充说明:如果你的披萨数据是后端接口返回,也可以选择把搜索关键词传给后端做服务端过滤,仅需在
setSearchKeyword时调用后端搜索接口即可,整体逻辑和前端过滤基本一致。
内容的提问来源于stack exchange,提问作者ianclark226
相关产品推荐
相关产品推荐

