React TypeScript可折叠侧边栏优化及类型错误修复咨询
问题解决与优化方案
一、修复prev处的TypeScript错误
错误原因
代码中useState(open)里的open是未定义变量,TypeScript误将其推断为全局的window.open类型(即Window | null),导致setIsOpen的回调返回布尔值!prev时,与状态类型Window | null不匹配,触发类型报错。
修复步骤
- 初始化正确的布尔状态:将
useState(open)改为传入布尔值(true或false),明确状态类型:
const [isOpen, setIsOpen] = useState(true); // 默认打开,或改为false默认关闭
- 可选:显式指定类型:如果需要更严谨的类型声明,可添加泛型:
const [isOpen, setIsOpen] = useState<boolean>(true);
修复后setIsOpen((prev) => !prev)可正常工作,此时prev类型为boolean,返回值也符合状态类型要求。
二、可折叠侧边栏的优化实现方案
1. 简化条件渲染,减少代码冗余
原代码重复编写两套结构,可抽离变化部分简化逻辑:
import "./SidePanel.css"; import { useState } from "react"; const SidePanel = () => { const [isOpen, setIsOpen] = useState<boolean>(true); const handleToggle = () => { setIsOpen((prev) => !prev); }; return ( <nav id="Side-Panel-Wrapper"> <div className={`Side-Panel-Top-Bar-Wrapper ${isOpen ? "open" : "closed"}`}> {isOpen && <button>Logo</button>} <button onClick={handleToggle}>{isOpen ? "Close" : "Open"}</button> </div> <div className={`Side-Pannel-Navigation-Main-Wrapper ${isOpen ? "open" : "closed"}`}> {isOpen ? "search stuff" : "logo"} </div> </nav> ); }; export default SidePanel;
2. 用CSS类控制样式,分离逻辑
通过给容器添加open/closed类,让CSS负责样式切换,减少JSX中的判断:
/* 示例:通过父类控制子元素显示 */ #Side-Panel-Wrapper .Side-Panel-Top-Bar-Wrapper button:first-child { display: none; } #Side-Panel-Wrapper .Side-Pannel-Navigation-Main-Wrapper { content: "logo"; } #Side-Panel-Wrapper.open .Side-Panel-Top-Bar-Wrapper button:first-child { display: block; } #Side-Panel-Wrapper.open .Side-Pannel-Navigation-Main-Wrapper { content: "search stuff"; }
这样JSX只需维护isOpen状态,样式逻辑完全交给CSS,代码更简洁。
3. 提取独立组件(可选)
若侧边栏结构复杂,可拆分顶部栏、内容区为独立组件,提升复用性:
const SidePanelTopBar = ({ isOpen, onToggle }: { isOpen: boolean; onToggle: () => void }) => ( <div className={`Side-Panel-Top-Bar-Wrapper ${isOpen ? "open" : "closed"}`}> {isOpen && <button>Logo</button>} <button onClick={onToggle}>{isOpen ? "Close" : "Open"}</button> </div> ); const SidePanelContent = ({ isOpen }: { isOpen: boolean }) => ( <div className={`Side-Pannel-Navigation-Main-Wrapper ${isOpen ? "open" : "closed"}`}> {isOpen ? "search stuff" : "logo"} </div> ); // 主组件 const SidePanel = () => { const [isOpen, setIsOpen] = useState<boolean>(true); const handleToggle = () => setIsOpen(prev => !prev); return ( <nav id="Side-Panel-Wrapper"> <SidePanelTopBar isOpen={isOpen} onToggle={handleToggle} /> <SidePanelContent isOpen={isOpen} /> </nav> ); };
4. 无障碍优化(可选)
添加ARIA属性,提升侧边栏的无障碍访问性:
<button onClick={handleToggle} aria-expanded={isOpen} aria-label={isOpen ? "关闭侧边栏" : "打开侧边栏"} > {isOpen ? "Close" : "Open"} </button>
内容的提问来源于stack exchange,提问作者JPWilson
相关产品推荐
相关产品推荐

