Skip to content

Commit d36dc28

Browse files
authored
Merge pull request #57 from pythonkr/feature/scroll-restoration-2026
feat: 페이지 이동 시 스크롤 상단 이동 시 스크롤 위치 복구
2 parents 1c5c967 + eb449a4 commit d36dc28

6 files changed

Lines changed: 99 additions & 72 deletions

File tree

apps/pyconkr-2025/src/App.tsx

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,8 @@ import { useBackendClient, useFlattenSiteMapQuery, useSponsorQuery } from "@fron
22
import { NestedSiteMapSchema } from "@frontend/common/schemas/backendAPI";
33
import { buildNestedSiteMap } from "@frontend/common/utils";
44
import { FC, useEffect } from "react";
5-
import { Route, Routes, useLocation } from "react-router-dom";
5+
import { Outlet, ScrollRestoration, useLocation } from "react-router-dom";
66
import { isEmpty, isNullish } from "remeda";
7-
8-
import MainLayout from "./components/layout/index.tsx";
9-
import { PageIdParamRenderer, RouteRenderer } from "./components/pages/dynamic_route.tsx";
10-
import { PresentationDetailPage } from "./components/pages/presentation_detail.tsx";
11-
import { ShopSignInPage } from "./components/pages/sign_in.tsx";
12-
import { SponsorDetailPage } from "./components/pages/sponsor_detail.tsx";
13-
import { Test } from "./components/pages/test.tsx";
14-
import { IS_DEBUG_ENV } from "./consts";
157
import { useAppContext } from "./contexts/app_context";
168

179
export const App: FC = () => {
@@ -45,15 +37,9 @@ export const App: FC = () => {
4537
}, [location, language, flatSiteMap, sponsorTiers]);
4638

4739
return (
48-
<Routes>
49-
<Route element={<MainLayout />}>
50-
{IS_DEBUG_ENV && <Route path="/debug" element={<Test />} />}
51-
<Route path="/account/sign-in" element={<ShopSignInPage />} />
52-
<Route path="/sponsors/:id" element={<SponsorDetailPage />} />
53-
<Route path="/presentations/:id" element={<PresentationDetailPage />} />
54-
<Route path="/pages/:id" element={<PageIdParamRenderer />} />
55-
<Route path="*" element={<RouteRenderer />} />
56-
</Route>
57-
</Routes>
40+
<>
41+
<ScrollRestoration />
42+
<Outlet />
43+
</>
5844
);
5945
};

apps/pyconkr-2025/src/main.tsx

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
1111
import { SnackbarProvider } from "notistack";
1212
import { FC, StrictMode, useState } from "react";
1313
import { createRoot } from "react-dom/client";
14-
import { BrowserRouter } from "react-router-dom";
14+
import { RouterProvider } from "react-router-dom";
1515

16-
import { App } from "./App.tsx";
16+
import { router } from "./router.tsx";
1717
import { IS_DEBUG_ENV } from "./consts";
1818
import { LOCAL_STORAGE_LANGUAGE_KEY } from "./consts/local_stroage.ts";
1919
import { PyConKRMDXComponents } from "./consts/mdx_components.ts";
@@ -84,23 +84,21 @@ export const MainApp: FC = () => {
8484
<QueryClientProvider client={queryClient}>
8585
<ReactQueryDevtools initialIsOpen={false} />
8686
<SnackbarProvider>
87-
<BrowserRouter>
88-
<AppContext.Provider value={{ ...appState, setAppContext }}>
89-
<CommonContextProvider options={{ ...CommonOptions, language: appState.language }}>
90-
<ShopContextProvider options={{ ...ShopOptions, language: appState.language }}>
91-
<ErrorBoundary fallback={ErrorFallback}>
92-
<Suspense fallback={SuspenseFallback}>
93-
<ThemeProvider theme={muiTheme}>
94-
<CssBaseline />
95-
<Global styles={globalStyles} />
96-
<App />
97-
</ThemeProvider>
98-
</Suspense>
99-
</ErrorBoundary>
100-
</ShopContextProvider>
101-
</CommonContextProvider>
102-
</AppContext.Provider>
103-
</BrowserRouter>
87+
<AppContext.Provider value={{ ...appState, setAppContext }}>
88+
<CommonContextProvider options={{ ...CommonOptions, language: appState.language }}>
89+
<ShopContextProvider options={{ ...ShopOptions, language: appState.language }}>
90+
<ErrorBoundary fallback={ErrorFallback}>
91+
<Suspense fallback={SuspenseFallback}>
92+
<ThemeProvider theme={muiTheme}>
93+
<CssBaseline />
94+
<Global styles={globalStyles} />
95+
<RouterProvider router={router} />
96+
</ThemeProvider>
97+
</Suspense>
98+
</ErrorBoundary>
99+
</ShopContextProvider>
100+
</CommonContextProvider>
101+
</AppContext.Provider>
104102
</SnackbarProvider>
105103
</QueryClientProvider>
106104
</StrictMode>

apps/pyconkr-2025/src/router.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { createBrowserRouter } from "react-router-dom";
2+
3+
import { App } from "./App.tsx";
4+
import MainLayout from "./components/layout/index.tsx";
5+
import { PageIdParamRenderer, RouteRenderer } from "./components/pages/dynamic_route.tsx";
6+
import { PresentationDetailPage } from "./components/pages/presentation_detail.tsx";
7+
import { ShopSignInPage } from "./components/pages/sign_in.tsx";
8+
import { SponsorDetailPage } from "./components/pages/sponsor_detail.tsx";
9+
import { Test } from "./components/pages/test.tsx";
10+
import { IS_DEBUG_ENV } from "./consts";
11+
12+
export const router = createBrowserRouter([
13+
{
14+
element: <App />,
15+
children: [
16+
{
17+
element: <MainLayout />,
18+
children: [
19+
...(IS_DEBUG_ENV ? [{ path: "/debug", element: <Test /> }] : []),
20+
{ path: "/account/sign-in", element: <ShopSignInPage /> },
21+
{ path: "/sponsors/:id", element: <SponsorDetailPage /> },
22+
{ path: "/presentations/:id", element: <PresentationDetailPage /> },
23+
{ path: "/pages/:id", element: <PageIdParamRenderer /> },
24+
{ path: "*", element: <RouteRenderer /> },
25+
],
26+
},
27+
],
28+
},
29+
]);

apps/pyconkr-2026/src/App.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@ import { useBackendClient, useFlattenSiteMapQuery, useSponsorQuery } from "@fron
22
import { NestedSiteMapSchema } from "@frontend/common/schemas/backendAPI";
33
import { buildNestedSiteMap } from "@frontend/common/utils";
44
import { FC, useEffect } from "react";
5-
import { Route, Routes, useLocation } from "react-router-dom";
5+
import { Outlet, ScrollRestoration, useLocation } from "react-router-dom";
66
import { isEmpty, isNullish } from "remeda";
77

8-
import MainLayout from "./components/layout/index.tsx";
9-
import { PageIdParamRenderer, RouteRenderer } from "./components/pages/dynamic_route.tsx";
10-
import { PresentationDetailPage } from "./components/pages/presentation_detail.tsx";
11-
import { ShopSignInPage } from "./components/pages/sign_in.tsx";
12-
import { SponsorDetailPage } from "./components/pages/sponsor_detail.tsx";
138
import { useAppContext } from "./contexts/app_context";
149

1510
export const App: FC = () => {
@@ -43,14 +38,9 @@ export const App: FC = () => {
4338
}, [location, language, flatSiteMap, sponsorTiers]);
4439

4540
return (
46-
<Routes>
47-
<Route element={<MainLayout />}>
48-
<Route path="/account/sign-in" element={<ShopSignInPage />} />
49-
<Route path="/sponsors/:id" element={<SponsorDetailPage />} />
50-
<Route path="/presentations/:id" element={<PresentationDetailPage />} />
51-
<Route path="/pages/:id" element={<PageIdParamRenderer />} />
52-
<Route path="*" element={<RouteRenderer />} />
53-
</Route>
54-
</Routes>
41+
<>
42+
<ScrollRestoration />
43+
<Outlet />
44+
</>
5545
);
5646
};

apps/pyconkr-2026/src/main.tsx

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
1111
import { SnackbarProvider } from "notistack";
1212
import { FC, StrictMode, useState } from "react";
1313
import { createRoot } from "react-dom/client";
14-
import { BrowserRouter } from "react-router-dom";
14+
import { RouterProvider } from "react-router-dom";
1515

16-
import { App } from "./App.tsx";
1716
import { IS_DEBUG_ENV } from "./consts";
1817
import { LOCAL_STORAGE_LANGUAGE_KEY } from "./consts/local_stroage.ts";
1918
import { PyConKRMDXComponents } from "./consts/mdx_components.ts";
2019
import { AppContext, AppContextType } from "./contexts/app_context.tsx";
20+
import { router } from "./router.tsx";
2121
import { globalStyles, muiTheme } from "./styles/globalStyles.ts";
2222

2323
const queryClient = new QueryClient({
@@ -84,23 +84,21 @@ export const MainApp: FC = () => {
8484
<QueryClientProvider client={queryClient}>
8585
<ReactQueryDevtools initialIsOpen={false} />
8686
<SnackbarProvider>
87-
<BrowserRouter>
88-
<AppContext.Provider value={{ ...appState, setAppContext }}>
89-
<CommonContextProvider options={{ ...CommonOptions, language: appState.language }}>
90-
<ShopContextProvider options={{ ...ShopOptions, language: appState.language }}>
91-
<ErrorBoundary fallback={ErrorFallback}>
92-
<Suspense fallback={SuspenseFallback}>
93-
<ThemeProvider theme={muiTheme}>
94-
<CssBaseline />
95-
<Global styles={globalStyles} />
96-
<App />
97-
</ThemeProvider>
98-
</Suspense>
99-
</ErrorBoundary>
100-
</ShopContextProvider>
101-
</CommonContextProvider>
102-
</AppContext.Provider>
103-
</BrowserRouter>
87+
<AppContext.Provider value={{ ...appState, setAppContext }}>
88+
<CommonContextProvider options={{ ...CommonOptions, language: appState.language }}>
89+
<ShopContextProvider options={{ ...ShopOptions, language: appState.language }}>
90+
<ErrorBoundary fallback={ErrorFallback}>
91+
<Suspense fallback={SuspenseFallback}>
92+
<ThemeProvider theme={muiTheme}>
93+
<CssBaseline />
94+
<Global styles={globalStyles} />
95+
<RouterProvider router={router} />
96+
</ThemeProvider>
97+
</Suspense>
98+
</ErrorBoundary>
99+
</ShopContextProvider>
100+
</CommonContextProvider>
101+
</AppContext.Provider>
104102
</SnackbarProvider>
105103
</QueryClientProvider>
106104
</StrictMode>

apps/pyconkr-2026/src/router.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { createBrowserRouter } from "react-router-dom";
2+
3+
import { App } from "./App.tsx";
4+
import MainLayout from "./components/layout/index.tsx";
5+
import { PageIdParamRenderer, RouteRenderer } from "./components/pages/dynamic_route.tsx";
6+
import { PresentationDetailPage } from "./components/pages/presentation_detail.tsx";
7+
import { ShopSignInPage } from "./components/pages/sign_in.tsx";
8+
import { SponsorDetailPage } from "./components/pages/sponsor_detail.tsx";
9+
10+
export const router = createBrowserRouter([
11+
{
12+
element: <App />,
13+
children: [
14+
{
15+
element: <MainLayout />,
16+
children: [
17+
{ path: "/account/sign-in", element: <ShopSignInPage /> },
18+
{ path: "/sponsors/:id", element: <SponsorDetailPage /> },
19+
{ path: "/presentations/:id", element: <PresentationDetailPage /> },
20+
{ path: "/pages/:id", element: <PageIdParamRenderer /> },
21+
{ path: "*", element: <RouteRenderer /> },
22+
],
23+
},
24+
],
25+
},
26+
]);

0 commit comments

Comments
 (0)