ReactJS/NextJS中实现Search组件过滤Card组件数据的方法
搜索过滤功能的组件间实现方案
核心思路:状态提升到共同父组件
这是React中组件间通信最直接的方案,将搜索关键词和菜单数据的状态托管在两个组件的共同父组件中,由父组件统一处理数据获取、过滤逻辑,并将结果传递给Card组件,同时监听Search组件的输入变化更新搜索关键词。
代码实现示例
1. 父组件(如 MenuContainer.jsx)
负责数据获取、状态管理和过滤逻辑:
import { useState, useEffect } from 'react'; import Search from './Search'; import Card from './Card'; const MenuContainer = () => { const [menuData, setMenuData] = useState([]); const [searchTerm, setSearchTerm] = useState(''); // 从API获取初始菜单数据 useEffect(() => { const fetchMenuData = async () => { try { const response = await fetch('你的菜单API地址'); const data = await response.json(); setMenuData(data); } catch (error) { console.error('菜单数据加载失败:', error); } }; fetchMenuData(); }, []); // 根据搜索关键词过滤数据 const filteredMenuData = menuData.filter(item => // 可根据实际字段调整,比如名称、描述等 item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( <div className="menu-wrapper"> <Search onSearchInputChange={setSearchTerm} /> <Card menuItems={filteredMenuData} /> </div> ); }; export default MenuContainer;
2. 搜索组件(Search.jsx)
仅负责输入UI和将输入值传递给父组件:
const Search = ({ onSearchInputChange }) => { return ( <div className="search-bar"> <input type="text" placeholder="搜索菜单..." onChange={(e) => onSearchInputChange(e.target.value)} /> </div> ); }; export default Search;
3. 卡片组件(Card.jsx)
仅负责接收过滤后的数据并渲染:
const Card = ({ menuItems }) => { if (menuItems.length === 0) { return <p>未找到匹配的菜单</p>; } return ( <div className="card-grid"> {menuItems.map(item => ( <div key={item.id} className="menu-card"> <h3>{item.name}</h3> <p>{item.description}</p> <span className="price">¥{item.price}</span> </div> ))} </div> ); }; export default Card;
备选方案:使用Context API(适合层级较深的组件结构)
如果Search和Card组件在组件树中层级较深,props层层传递会显得繁琐,可以用Context API统一管理搜索状态和菜单数据:
代码实现示例
1. 创建Context(MenuContext.jsx)
import { createContext, useState, useEffect, useContext } from 'react'; const MenuContext = createContext(); export const MenuProvider = ({ children }) => { const [menuData, setMenuData] = useState([]); const [searchTerm, setSearchTerm] = useState(''); useEffect(() => { const fetchMenuData = async () => { const response = await fetch('你的菜单API地址'); const data = await response.json(); setMenuData(data); }; fetchMenuData(); }, []); const filteredData = menuData.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( <MenuContext.Provider value={{ filteredData, setSearchTerm }}> {children} </MenuContext.Provider> ); }; // 自定义Hook简化Context调用 export const useMenuContext = () => useContext(MenuContext);
2. 修改Search组件
import { useMenuContext } from './MenuContext'; const Search = () => { const { setSearchTerm } = useMenuContext(); return ( <div className="search-bar"> <input type="text" placeholder="搜索菜单..." onChange={(e) => setSearchTerm(e.target.value)} /> </div> ); }; export default Search;
3. 修改Card组件
import { useMenuContext } from './MenuContext'; const Card = () => { const { filteredData } = useMenuContext(); if (filteredData.length === 0) { return <p>未找到匹配的菜单</p>; } return ( <div className="card-grid"> {filteredData.map(item => ( <div key={item.id} className="menu-card"> <h3>{item.name}</h3> <p>{item.description}</p> <span className="price">¥{item.price}</span> </div> ))} </div> ); }; export default Card;
4. 在根组件中包裹Provider
import { MenuProvider } from './MenuContext'; import Search from './Search'; import Card from './Card'; const App = () => { return ( <MenuProvider> <Search /> <Card /> </MenuProvider> ); }; export default App;
内容的提问来源于stack exchange,提问作者Python Student
相关产品推荐
相关产品推荐

