refactor(routing): Migrate to React Router and simplify component structure

Replaces 'wouter' with 'react-router-dom' to standardize the routing library and resolve dependency conflicts.

Key changes:

- All routing logic, including hooks (useLocation) and components (Link, Routes), now uses 'react-router-dom'.

- The component tree has been simplified by removing the MainContainer component and moving its layout directly into App.tsx.

- The <BrowserRouter> provider is now correctly placed at the application's entry point in main.tsx.
This commit is contained in:
2025-09-24 15:43:34 +09:00
parent 997d134581
commit df61ce27e0
9 changed files with 118 additions and 67 deletions

View File

@@ -19,9 +19,9 @@
"lucide-react": "^0.544.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router-dom": "^7.9.1",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.13",
"wouter": "^3.7.1",
"zustand": "^5.0.8"
},
"devDependencies": {
@@ -29,6 +29,7 @@
"@types/node": "^24.3.1",
"@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7",
"@types/react-router-dom": "^5.3.3",
"@vitejs/plugin-react-swc": "^4.1.0",
"eslint": "^9.33.0",
"eslint-plugin-react-hooks": "^5.2.0",

View File

@@ -1,7 +1,17 @@
import MainContainer from './components/MainContainer';
import PageContainer from './components/PageContainer';
import Sidebar from './components/Sidebar';
import { ThemeButton } from './components/ThemeButton';
function App() {
return <MainContainer />;
}
const App = () => {
return (
<div className="flex h-screen">
<Sidebar />
<PageContainer />
<div className="absolute bottom-4 right-4">
<ThemeButton />
</div>
</div>
);
};
export default App;

View File

@@ -1,17 +0,0 @@
import PageContainer from './PageContainer';
import Sidebar from './Sidebar';
import { ToggleTheme } from './ToggleTheme';
const MainContainer = () => {
return (
<div className="flex h-screen">
<Sidebar />
<PageContainer />
<div className="absolute bottom-4 right-4">
<ToggleTheme />
</div>
</div>
);
};
export default MainContainer;

View File

@@ -1,4 +1,4 @@
import { Route, Switch } from 'wouter';
import { Routes, Route } from 'react-router-dom';
import Topbar from './Topbar';
@@ -11,12 +11,12 @@ const PageContainer = () => {
return (
<div className="flex flex-col flex-1">
<Topbar />
<Switch>
<Route path="/" component={Home} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/todos" component={Todos} />
<Route component={NotFound} />
</Switch>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/todos" element={<Todos />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
};

View File

@@ -1,5 +1,5 @@
import { Button } from '@/components/ui/button';
import { useLocation, Link } from 'wouter';
import { Link, useLocation } from 'react-router-dom';
import {
IconHome,
IconCalendarWeekFilled,
@@ -16,7 +16,7 @@ export const items = [
];
const Sidebar = () => {
const [location] = useLocation();
const location = useLocation();
return (
<nav className="flex flex-col min-w-[240px] max-w-[480px] bg-sidebar border">
<div className="flex flex-col m-2 gap-2">
@@ -26,10 +26,10 @@ const Sidebar = () => {
asChild
size="sm"
key={item.name}
variant={location === item.href ? 'secondary' : 'ghost'}
variant={location.pathname === item.href ? 'secondary' : 'ghost'}
className="justify-start"
>
<Link href={item.href}>
<Link to={item.href}>
<item.icon /> {item.name}
</Link>
</Button>

View File

@@ -5,7 +5,7 @@ import { Button } from '@/components/ui/button';
import { useTheme } from '../hooks/useThemeHook';
import { changeTheme } from '../lib/utils';
export const ToggleTheme = () => {
export const ThemeButton = () => {
const { theme, toggleTheme } = useTheme();
useEffect(() => {

View File

@@ -1,13 +1,14 @@
import { useLocation } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { items } from './Sidebar';
import { useLocation } from 'wouter';
const Topbar = () => {
const [location] = useLocation();
const location = useLocation();
return (
<div className="flex bg-sidebar p-2 gap-2 border-t border-r border-b border-l-0">
<Button variant="ghost" size="sm" className="font-semibold">
{items.find((item) => item.href === location)?.name}
{items.find((item) => item.href === location.pathname)?.name}
{/* TODO: Add Sidebar Items(Pages, etc...) to Zustand Store */}
</Button>
</div>

View File

@@ -1,10 +1,13 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import './styles/index.css';
import App from './App.tsx';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
);

111
yarn.lock
View File

@@ -1066,6 +1066,13 @@ __metadata:
languageName: node
linkType: hard
"@types/history@npm:^4.7.11":
version: 4.7.11
resolution: "@types/history@npm:4.7.11"
checksum: 10c0/3facf37c2493d1f92b2e93a22cac7ea70b06351c2ab9aaceaa3c56aa6099fb63516f6c4ec1616deb5c56b4093c026a043ea2d3373e6c0644d55710364d02c934
languageName: node
linkType: hard
"@types/json-schema@npm:^7.0.15":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
@@ -1091,6 +1098,36 @@ __metadata:
languageName: node
linkType: hard
"@types/react-router-dom@npm:^5.3.3":
version: 5.3.3
resolution: "@types/react-router-dom@npm:5.3.3"
dependencies:
"@types/history": "npm:^4.7.11"
"@types/react": "npm:*"
"@types/react-router": "npm:*"
checksum: 10c0/a9231a16afb9ed5142678147eafec9d48582809295754fb60946e29fcd3757a4c7a3180fa94b45763e4c7f6e3f02379e2fcb8dd986db479dcab40eff5fc62a91
languageName: node
linkType: hard
"@types/react-router@npm:*":
version: 5.1.20
resolution: "@types/react-router@npm:5.1.20"
dependencies:
"@types/history": "npm:^4.7.11"
"@types/react": "npm:*"
checksum: 10c0/1f7eee61981d2f807fa01a34a0ef98ebc0774023832b6611a69c7f28fdff01de5a38cabf399f32e376bf8099dcb7afaf724775bea9d38870224492bea4cb5737
languageName: node
linkType: hard
"@types/react@npm:*":
version: 19.1.13
resolution: "@types/react@npm:19.1.13"
dependencies:
csstype: "npm:^3.0.2"
checksum: 10c0/75e35b54883f5ed07d3b5cb16a4711b6dbb7ec6b74301bcb9bfa697c9d9fff022ec508e1719e7b2c69e2e8b042faac1125be7717b5e5e084f816a2c88e136920
languageName: node
linkType: hard
"@types/react@npm:^19.1.10":
version: 19.1.12
resolution: "@types/react@npm:19.1.12"
@@ -1448,6 +1485,13 @@ __metadata:
languageName: node
linkType: hard
"cookie@npm:^1.0.1":
version: 1.0.2
resolution: "cookie@npm:1.0.2"
checksum: 10c0/fd25fe79e8fbcfcaf6aa61cd081c55d144eeeba755206c058682257cb38c4bd6795c6620de3f064c740695bb65b7949ebb1db7a95e4636efb8357a335ad3f54b
languageName: node
linkType: hard
"cross-spawn@npm:^7.0.6":
version: 7.0.6
resolution: "cross-spawn@npm:7.0.6"
@@ -1906,6 +1950,7 @@ __metadata:
"@types/node": "npm:^24.3.1"
"@types/react": "npm:^19.1.10"
"@types/react-dom": "npm:^19.1.7"
"@types/react-router-dom": "npm:^5.3.3"
"@vitejs/plugin-react-swc": "npm:^4.1.0"
class-variance-authority: "npm:^0.7.1"
clsx: "npm:^2.1.1"
@@ -1916,13 +1961,13 @@ __metadata:
lucide-react: "npm:^0.544.0"
react: "npm:^19.1.1"
react-dom: "npm:^19.1.1"
react-router-dom: "npm:^7.9.1"
tailwind-merge: "npm:^3.3.1"
tailwindcss: "npm:^4.1.13"
tw-animate-css: "npm:^1.3.8"
typescript: "npm:~5.8.3"
typescript-eslint: "npm:^8.39.1"
vite: "npm:^7.1.2"
wouter: "npm:^3.7.1"
zustand: "npm:^5.0.8"
languageName: unknown
linkType: soft
@@ -2496,13 +2541,6 @@ __metadata:
languageName: node
linkType: hard
"mitt@npm:^3.0.1":
version: 3.0.1
resolution: "mitt@npm:3.0.1"
checksum: 10c0/3ab4fdecf3be8c5255536faa07064d05caa3dd332bd318ff02e04621f7b3069ca1de9106cfe8e7ced675abfc2bec2ce4c4ef321c4a1bb1fb29df8ae090741913
languageName: node
linkType: hard
"mkdirp@npm:^3.0.1":
version: 3.0.1
resolution: "mkdirp@npm:3.0.1"
@@ -2733,6 +2771,34 @@ __metadata:
languageName: node
linkType: hard
"react-router-dom@npm:^7.9.1":
version: 7.9.1
resolution: "react-router-dom@npm:7.9.1"
dependencies:
react-router: "npm:7.9.1"
peerDependencies:
react: ">=18"
react-dom: ">=18"
checksum: 10c0/a211b9e6d69e6efc9b55cfc0f1eb8a772832f86b13fd16a6d89befb78ff6bfc06d9cc48abf4b96420edd81a07216f910c15afb0769ae4d4f445b59d4e2ec9376
languageName: node
linkType: hard
"react-router@npm:7.9.1":
version: 7.9.1
resolution: "react-router@npm:7.9.1"
dependencies:
cookie: "npm:^1.0.1"
set-cookie-parser: "npm:^2.6.0"
peerDependencies:
react: ">=18"
react-dom: ">=18"
peerDependenciesMeta:
react-dom:
optional: true
checksum: 10c0/27448e4c84199d240f6a15d503cf26509320fd4ea31aec6f12a427ac4a560a320321e9b119981eddad25801c062be0f814d4461174f69efdc9f9e5af14cf6915
languageName: node
linkType: hard
"react@npm:^19.1.1":
version: 19.1.1
resolution: "react@npm:19.1.1"
@@ -2740,13 +2806,6 @@ __metadata:
languageName: node
linkType: hard
"regexparam@npm:^3.0.0":
version: 3.0.0
resolution: "regexparam@npm:3.0.0"
checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459
languageName: node
linkType: hard
"reselect@npm:^5.1.1":
version: 5.1.1
resolution: "reselect@npm:5.1.1"
@@ -2885,6 +2944,13 @@ __metadata:
languageName: node
linkType: hard
"set-cookie-parser@npm:^2.6.0":
version: 2.7.1
resolution: "set-cookie-parser@npm:2.7.1"
checksum: 10c0/060c198c4c92547ac15988256f445eae523f57f2ceefeccf52d30d75dedf6bff22b9c26f756bd44e8e560d44ff4ab2130b178bd2e52ef5571bf7be3bd7632d9a
languageName: node
linkType: hard
"shebang-command@npm:^2.0.0":
version: 2.0.0
resolution: "shebang-command@npm:2.0.0"
@@ -3170,7 +3236,7 @@ __metadata:
languageName: node
linkType: hard
"use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.5.0":
"use-sync-external-store@npm:^1.5.0":
version: 1.5.0
resolution: "use-sync-external-store@npm:1.5.0"
peerDependencies:
@@ -3263,19 +3329,6 @@ __metadata:
languageName: node
linkType: hard
"wouter@npm:^3.7.1":
version: 3.7.1
resolution: "wouter@npm:3.7.1"
dependencies:
mitt: "npm:^3.0.1"
regexparam: "npm:^3.0.0"
use-sync-external-store: "npm:^1.0.0"
peerDependencies:
react: ">=16.8.0"
checksum: 10c0/1974f32f425c1cf6412e6946936e37db3a283e6e6965acd336ce04d67bb36fbf2c40fc90a1bc4537930b326e370b5e053437e0f80554cb94d34ec8c354b86693
languageName: node
linkType: hard
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0"