ReactJS无路由组件切换:按侧边栏选择渲染对应页面
React无路由切换组件修复方案
问题分析
你的代码存在三个核心问题导致组件无法正确切换:
- Dashboard组件用useEffect控制渲染内容错误:直接在useEffect中给变量赋值,React渲染机制会导致变量在组件重渲染时被重置,且useEffect是副作用钩子,不适合用来控制UI渲染。
- 未处理Shop组件的渲染逻辑:Dashboard只判断了
executables分支,点击Shop按钮后没有对应组件渲染。 - Sidebar中Settings按钮的onClick写法错误:直接调用
setSection("settings")会导致组件挂载时立即执行,而非点击时触发。
修复代码
1. 修改Components/Dashboard.tsx
去掉useEffect,改用组件映射的方式直接返回对应内容:
import styled from "styled-components" import Executable from "./Executable" import Shop from "./Shop" // 确保导入Shop组件 import Navbar from "./Navbar" type EntryProps = { section: string } const Dashboard = ({ section }: EntryProps) => { // 用对象映射组件,简洁易维护 const sectionMap = { executables: ( <div className="grid"> <div className="row"> <Executable /> </div> </div> ), shop: <Shop /> } return ( <Section> <Navbar /> {/* 渲染对应组件,无匹配时返回null */} {sectionMap[section as keyof typeof sectionMap] || null} </Section> ) } // 补充组件导出(原代码遗漏) export default Dashboard
2. 修改Components/Sidebar.tsx
修复Settings按钮的onClick逻辑,移除Shop按钮中不必要的e.preventDefault():
import styled from "styled-components" import { FaBars } from "react-icons/fa" import { BsFileEarmarkBinary } from "react-icons/bs" import { BiLogOut } from "react-icons/bi" import { AiOutlineShoppingCart } from "react-icons/ai" import { IoMdSettings } from "react-icons/io" import { useState } from "react" // 给setSection定义精确类型,替代模糊的Function type SidebarProps = { section: string setSection: (name: string) => void } const Sidebar = ({ section, setSection }: SidebarProps) => { const [disabled, setDisabled] = useState(true) const handleDisabled = () => setDisabled(!disabled) return ( <Aside id="aside"> <div className={disabled ? "brand center" : "brand"} onClick={handleDisabled} > <FaBars /> </div> <ul className="links"> <li> <BsFileEarmarkBinary /> <span className={disabled ? "disabled" : ""} onClick={() => setSection("executables")} > Executables </span> </li> <li> <AiOutlineShoppingCart /> <span className={disabled ? "disabled" : ""} onClick={() => setSection("shop")} > Shop </span> </li> <li> <IoMdSettings /> <span className={disabled ? "disabled" : ""} onClick={() => setSection("settings")} {/* 修复为箭头函数 */} > Settings </span> </li> </ul> <div className="logout"> <BiLogOut /> </div> </Aside> ) } export default Sidebar
3. 补充Pages/DashboardPage.tsx的样式与导出(原代码遗漏)
import styled from "styled-components" import Sidebar from "../components/Sidebar" import Rightsidebar from "../components/Rightsidebar" import Dashboard from "../components/Dashboard" import { useState } from "react" // 补充容器样式(根据你的需求自定义) const Div = styled.div` display: flex; width: 100vw; height: 100vh; ` const DashboardPage = () => { const [page, setPage] = useState("executables") const setSection = (name: string) => { setPage(name) } return ( <Div> <Sidebar section={page} setSection={setSection} /> <Dashboard section={page} /> <Rightsidebar /> </Div> ) } export default DashboardPage
额外优化建议
- 可以给section设置默认 fallback 组件,避免未匹配时页面空白。
- 后续新增页面只需在
sectionMap中添加键值对即可,无需修改渲染逻辑,扩展性更强。
内容的提问来源于stack exchange,提问作者iwrenx
相关产品推荐
相关产品推荐

