React侧边栏过滤器状态优化:解决代码臃肿且保留原有功能
优化过滤器侧边栏状态管理与代码精简方案
1. 合并过滤器展开状态,减少重复useState
把多个分散的过滤器展开状态合并为一个对象,用单个useState管理,同时编写通用的状态切换函数,避免重复定义setFilterXOpen:
const [filterExpansions, setFilterExpansions] = useState({ filterOne: false, filterTwo: false, filterThree: false, filterFour: false }); const toggleFilterExpansion = (filterKey) => { setFilterExpansions(prev => ({ ...prev, [filterKey]: !prev[filterKey] })); };
2. 抽离侧边栏渲染逻辑,消除重复代码
将两次渲染FiltersSideBar的逻辑封装成一个函数,避免重复编写props和条件判断:
const renderFiltersSidebar = (className = "") => ( <FiltersSideBar className={className} filterExpansions={filterExpansions} toggleFilterExpansion={toggleFilterExpansion} /> );
之后在JSX中直接调用该函数即可:
{size.width > 600 && renderFiltersSidebar()} {size.width <= 600 && !hideSidebar && renderFiltersSidebar("overlay")}
3. 将过滤器状态移入Context,彻底取消props传递
利用已有的AppContext,把过滤器的展开状态和切换函数加入Context的value中:
<AppContext.Provider value={{ filters, setFilters, filterExpansions, toggleFilterExpansion }}>
在FiltersSideBar组件内直接通过useContext获取状态和方法,无需再接收大量props:
// FiltersSideBar.js import { useContext } from 'react'; import AppContext from './AppContext'; const FiltersSideBar = ({ className = "" }) => { const { filterExpansions, toggleFilterExpansion } = useContext(AppContext); // 使用示例:filterExpansions.filterOne 就是原filterOneOpen的状态 // 切换示例:toggleFilterExpansion('filterOne') return ( // 侧边栏原有内容 ); };
完整修改后的App.js代码
export default function App() { const [hideSidebar, setHideSidebar] = useState(true); // 合并过滤器展开状态 const [filterExpansions, setFilterExpansions] = useState({ filterOne: false, filterTwo: false, filterThree: false, filterFour: false }); // 通用切换函数 const toggleFilterExpansion = (filterKey) => { setFilterExpansions(prev => ({ ...prev, [filterKey]: !prev[filterKey] })); }; // 抽离侧边栏渲染逻辑 const renderFiltersSidebar = (className = "") => ( <FiltersSideBar className={className} /> ); return ( <ThemeProvider theme={theme}> <BrowserRouter> <AppContext.Provider value={{ filters, setFilters, filterExpansions, toggleFilterExpansion }}> <div style={{display: 'flex', backgroundColor: '#f6f7f9'}}> <button className="overlay-button-hidden" style={{display: size.width > 600 ? "none" : "inline"}} onClick={() => setHideSidebar(prev => !prev)} > <ArrowBackIosNewIcon /> </button> {size.width > 600 && renderFiltersSidebar()} <div style={{ display: "flex" }}> {size.width <= 600 && !hideSidebar && renderFiltersSidebar("overlay")} {size.width <= 600 && !hideSidebar && ( <button className="overlay-button" style={{display: size.width > 600 ? "none" : "inline"}} onClick={() => setHideSidebar(prev => !prev)} > <ArrowBackIosNewIcon /> </button> )} </div> <Routes> <Route path="*" element={<Navigate to="/devices" replace />} /> </Routes> </div> </AppContext.Provider> </BrowserRouter> </ThemeProvider> ); }
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

