React父子组件通信:实现城市名称排序卡片功能的问题
解决方案
核心思路
父组件维护城市数据和排序状态,通过传递回调函数给子组件,让子组件触发父组件的排序逻辑,最终由父组件更新状态并渲染排序后的卡片。
1. 父组件(Home)实现
父组件负责管理原始城市数据、排序状态,以及排序逻辑的实现:
import { useState, useMemo } from 'react'; import FilterComponent from './FilterComponent'; import CityCard from './CityCard'; function Home() { // 原始城市数据,根据你的实际结构调整 const [cities, setCities] = useState([ { id: 1, name: 'Tokyo', country: 'Japan' }, { id: 2, name: 'London', country: 'UK' }, { id: 3, name: 'Paris', country: 'France' }, ]); // 排序类型:null=不排序,'name'=按名称排序 const [sortType, setSortType] = useState(null); // 排序方向:asc=升序,desc=降序(可选,用于切换排序方向) const [sortDirection, setSortDirection] = useState('asc'); // 缓存排序后的结果,避免重复计算 const sortedCities = useMemo(() => { if (sortType !== 'name') return [...cities]; // 按名称字典序排序,支持大小写不敏感的排序 return [...cities].sort((a, b) => { const compareResult = a.name.toLowerCase().localeCompare(b.name.toLowerCase()); return sortDirection === 'desc' ? -compareResult : compareResult; }); }, [cities, sortType, sortDirection]); // 传给子组件的回调:触发按名称排序,同时切换方向 const handleSortByName = () => { setSortType('name'); setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'); }; return ( <div className="home-container"> {/* 把回调函数传给子组件 */} <FilterComponent onSortByName={handleSortByName} /> <div className="city-cards-grid"> {sortedCities.map(city => ( <CityCard key={city.id} city={city} /> ))} </div> </div> ); } export default Home;
2. 子组件(FilterComponent)实现
子组件不需要维护任何状态,只需要接收父组件的回调函数,在点击按钮时调用它:
function FilterComponent({ onSortByName }) { return ( <div className="filter-bar"> {/* 点击按钮触发父组件的排序逻辑 */} <button onClick={onSortByName} className="sort-btn"> City Name </button> </div> ); } export default FilterComponent;
关键注意事项
- 状态不可变性:排序时必须创建新数组(
[...cities]),不能直接修改原数组。React依赖状态的引用变化来检测更新,直接修改原数组会导致组件不重新渲染(解决你之前遇到的渲染问题)。 - 单一数据源:所有与城市数据、排序相关的状态都放在父组件中,子组件只负责触发操作,避免状态分散导致的维护问题。
- 性能优化:用
useMemo缓存排序后的数组,只有当依赖项(cities、sortType、sortDirection)变化时才重新计算排序结果,提升渲染性能。
内容的提问来源于stack exchange,提问作者Tushar Singh
相关产品推荐
相关产品推荐

