React项目切换分类后排序丢失且筛选无法自动触发问题求助
问题描述
我正在开发一个视频数据库应用,支持按分类筛选、按评分排序。切换筛选选项时功能正常,但切换视频分类后,排序不会自动触发,且排序状态会丢失。我已添加useEffect,但不清楚问题原因及调整方向,附上相关代码,请求帮助实现切换分类时保留排序状态。
更新内容:相关代码
HomePage组件
import * as _ from "lodash"; import { useEffect, useState } from "react"; import { getAllPrograms } from "../../helpers/getData"; import { TVProgram } from "../../models/models"; import Filters from "../Filters/Filters"; import ProgramsList from "../ProgramsList/ProgramsList"; import Sorting from "../Sorting/Sorting"; import "./HomePage.scss"; const HomePage = () => { const [programs, setPrograms] = useState<Array<TVProgram>>([]); const [category, setCategory] = useState<string>("movie,series"); const [sortedPrograms, setSortedPrograms] = useState<TVProgram[]>(programs); const getPrograms = async (category: string) => { const programs = await getAllPrograms(category); setPrograms(programs); }; useEffect(() => { getPrograms(category); }, [category]); const updateCategory = (categoryName: string): void => { setCategory(categoryName); console.log("catName", categoryName); }; const updatePrograms = (sortedPrograms: TVProgram[]): void => { setSortedPrograms(sortedPrograms); console.log("sortedPrograms", sortedPrograms); }; return ( <div className="container"> <div> <Filters updateCategory={updateCategory} currentCategory={category} ></Filters> <Sorting programs={programs} setPrograms={updatePrograms}></Sorting> </div> <ProgramsList programs={sortedPrograms}></ProgramsList> </div> ); }; export default HomePage;
Sorting组件
import _ from "lodash"; import { ChangeEvent, useEffect, useState } from "react"; import { sortProgramsByOrder } from "../../helpers/helpers"; import { TVProgram } from "../../models/models"; import "./Sorting.scss"; interface SortingListProps { programs: TVProgram[]; setPrograms: (programs: TVProgram[]) => void; } const Sorting = ({ programs, setPrograms }: SortingListProps) => { const OPTIONS = ["imdb rating descending", "imdb rating ascending"]; const [selectedOption, setSelectedOption] = useState<string>(""); const [sortedPrograms, setSortedPrograms] = useState<TVProgram[]>([]); useEffect(() => { if (selectedOption === OPTIONS[0]) { setSortedPrograms(sortProgramsByOrder(programs, "desc")); } else if (selectedOption === OPTIONS[1]) { setSortedPrograms(sortProgramsByOrder(programs, "asc")); } }, [selectedOption, programs]); const handleChange = (event: ChangeEvent<HTMLSelectElement>) => { console.log(); setSelectedOption(event.target.value); setPrograms(sortedPrograms); }; return ( <div> <select value={selectedOption} onChange={handleChange}> <option selected>Sortuj</option> {OPTIONS.map((option) => ( <option key={option} value={option} selected={option === selectedOption} > {option} </option> ))} </select> </div> ); }; export default Sorting;
问题原因分析
- 排序状态本地化丢失:排序选择的状态
selectedOption存储在Sorting组件内部,切换分类时HomePage重新获取数据并渲染,Sorting组件会被重新初始化,导致selectedOption重置为空,排序状态丢失。 - 新数据未自动应用排序:切换分类获取新的
programs后,Sorting组件的useEffect虽依赖programs,但此时selectedOption为空,不会执行排序逻辑,因此新数据不会自动排序。 - 状态更新时机错误:
handleChange中调用setPrograms(sortedPrograms)时,setSortedPrograms是异步操作,此时sortedPrograms还是旧值,无法正确传递最新排序结果。
解决方案及修改代码
1. 提升排序状态到父组件
将selectedOption从Sorting组件移到HomePage,确保切换分类时状态不会丢失,同时让父组件能在数据更新后自动应用排序规则。
修改后的HomePage组件
import * as _ from "lodash"; import { useEffect, useState } from "react"; import { getAllPrograms } from "../../helpers/getData"; import { TVProgram } from "../../models/models"; import Filters from "../Filters/Filters"; import ProgramsList from "../ProgramsList/ProgramsList"; import Sorting from "../Sorting/Sorting"; import { sortProgramsByOrder } from "../../helpers/helpers"; import "./HomePage.scss"; const HomePage = () => { const [programs, setPrograms] = useState<Array<TVProgram>>([]); const [category, setCategory] = useState<string>("movie,series"); const [sortedPrograms, setSortedPrograms] = useState<TVProgram[]>([]); // 把排序状态提升到父组件 const [sortOption, setSortOption] = useState<string>(""); const SORT_OPTIONS = ["imdb rating descending", "imdb rating ascending"]; const getPrograms = async (category: string) => { const programs = await getAllPrograms(category); setPrograms(programs); }; // 当分类或排序选项变化时,重新执行排序 useEffect(() => { let result = [...programs]; if (sortOption === SORT_OPTIONS[0]) { result = sortProgramsByOrder(programs, "desc"); } else if (sortOption === SORT_OPTIONS[1]) { result = sortProgramsByOrder(programs, "asc"); } setSortedPrograms(result); }, [programs, sortOption]); useEffect(() => { getPrograms(category); }, [category]); const updateCategory = (categoryName: string): void => { setCategory(categoryName); }; return ( <div className="container"> <div> <Filters updateCategory={updateCategory} currentCategory={category} ></Filters> <Sorting currentSortOption={sortOption} setSortOption={setSortOption} ></Sorting> </div> <ProgramsList programs={sortedPrograms}></ProgramsList> </div> ); }; export default HomePage;
修改后的Sorting组件
import { ChangeEvent } from "react"; import "./Sorting.scss"; interface SortingListProps { currentSortOption: string; setSortOption: (option: string) => void; } const Sorting = ({ currentSortOption, setSortOption }: SortingListProps) => { const OPTIONS = ["imdb rating descending", "imdb rating ascending"]; const handleChange = (event: ChangeEvent<HTMLSelectElement>) => { setSortOption(event.target.value); }; return ( <div> <select value={currentSortOption} onChange={handleChange}> <option value="">Sortuj</option> {OPTIONS.map((option) => ( <option key={option} value={option} > {option} </option> ))} </select> </div> ); }; export default Sorting;
修改说明
- 状态提升:将
sortOption移到HomePage,切换分类时状态不会被重置,保留用户的排序选择。 - 统一排序逻辑:在
HomePage中添加依赖programs和sortOption的useEffect,每当分类切换获取新数据,或用户修改排序选项时,自动执行排序并更新sortedPrograms。 - 简化Sorting组件:
Sorting仅负责展示下拉选项和传递排序选择,不再处理排序逻辑,职责更单一。 - 修正默认选项:将默认的空选项
value设为"",避免选中状态混乱。
内容的提问来源于stack exchange,提问作者guziczek300
相关产品推荐
相关产品推荐

