Skip to content

Commit 2a66c6c

Browse files
committed
fix: 몰라
1 parent ee6bf40 commit 2a66c6c

File tree

14 files changed

+79
-56
lines changed

14 files changed

+79
-56
lines changed

packages/react/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
}
1919
};
2020
</script>
21+
<!--app-data-->
2122
</head>
2223
<body class="bg-gray-50">
2324
<div id="root"><!--app-html--></div>

packages/react/server.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ app.use("*all", async (req, res) => {
5454

5555
const rendered = await render(pathname, req.query);
5656

57+
console.log(rendered);
58+
5759
const serialized = safeSerialize(rendered.__INITIAL_DATA__);
5860
const initialDataScript = `<script>window.__INITIAL_DATA__ = ${serialized};</script>`;
5961
const html = template
6062
.replace(`<!--app-head-->`, rendered.head ?? "")
6163
.replace(`<!--app-html-->`, rendered.html ?? "")
62-
.replace(`<!-- app-data -->`, initialDataScript);
64+
.replace(`<!--app-data-->`, initialDataScript);
6365

6466
res.status(200).set({ "Content-Type": "text/html" }).send(html);
6567
} catch (e) {

packages/react/src/entities/products/components/ProductDetail.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { useState } from "react";
2-
import { router } from "../../../router";
32
import type { StringRecord } from "../../../types";
43
import type { Product } from "../types";
54
import { PublicImage } from "../../../components";
65
import RelatedProducts from "./RelatedProducts";
76
import { useCartAddCommand } from "../../carts";
8-
import { log } from "../../../utils";
7+
import { useRouter } from "../../../router/hooks/useRouter.ts";
98

109
export function ProductDetail(product: Readonly<Product>) {
11-
log(`ProductDetail: ${product.productId}`);
10+
const router = useRouter();
1211
const addToCart = useCartAddCommand();
1312
const { productId, title, image, lprice, brand, category1, category2 } = product;
1413
const [cartQuantity, setCartQuantity] = useState(1);

packages/react/src/entities/products/components/ProductList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { ProductCard, ProductCardSkeleton } from "./ProductCard";
2-
import { router } from "../../../router";
32
import { PublicImage } from "../../../components";
43
import { useProductStoreContext } from "../hooks";
4+
import { useRouter } from "../../../router/hooks/useRouter.ts";
55

66
/**
77
* 상품 목록 컴포넌트
88
*/
99
export function ProductList() {
10+
const router = useRouter();
1011
const {
1112
state: { products, loading, error, totalCount },
1213
action: { loadProducts },

packages/react/src/entities/products/components/RelatedProducts.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { router } from "../../../router";
21
import { useProductStoreContext } from "../hooks";
2+
import { useRouter } from "../../../router/hooks/useRouter.ts";
33

44
export default function RelatedProducts() {
5+
const router = useRouter();
56
const {
67
state: { relatedProducts },
78
} = useProductStoreContext();

packages/react/src/entities/products/context/ProductContext.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { type createStore, type StringRecord } from "@hanghae-plus/lib";
1+
import { type createStore, type StringRecord, useStore } from "@hanghae-plus/lib";
22
import { getCategories, getProduct, getProducts } from "../../../api/productApi";
33
import { isNearBottom } from "../../../utils";
44
import { ProductStoreContext } from "../hooks";
55
import { initialProductState, PRODUCT_ACTIONS } from "../productStore";
6-
import { useStore } from "@hanghae-plus/lib";
7-
import { router } from "../../../router";
6+
import { useRouter } from "../../../router/hooks/useRouter.ts";
87

98
interface ProductProviderProps {
109
productStore: ReturnType<typeof createStore<typeof initialProductState, unknown>>;
@@ -15,6 +14,9 @@ const createErrorMessage = (error: unknown, defaultMessage = "알 수 없는 오
1514
error instanceof Error ? error.message : defaultMessage;
1615

1716
export const ProductProvider = ({ children, productStore }: ProductProviderProps) => {
17+
const router = useRouter();
18+
const query = router.query;
19+
1820
const productStoreState = useStore(productStore);
1921
const loadProducts = async (resetList = true) => {
2022
try {
@@ -26,7 +28,7 @@ export const ProductProvider = ({ children, productStore }: ProductProviderProps
2628
const {
2729
products,
2830
pagination: { total },
29-
} = await getProducts(router.query ?? {});
31+
} = await getProducts(query ?? {});
3032
const payload = { products, totalCount: total };
3133

3234
// 페이지 리셋이면 새로 설정, 아니면 기존에 추가
@@ -62,7 +64,7 @@ export const ProductProvider = ({ children, productStore }: ProductProviderProps
6264
pagination: { total },
6365
},
6466
categories,
65-
] = await Promise.all([getProducts(router.query), getCategories()]);
67+
] = await Promise.all([getProducts(query), getCategories()]);
6668

6769
// 페이지 리셋이면 새로 설정, 아니면 기존에 추가
6870
productStore.dispatch({

packages/react/src/main-server.tsx

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,47 @@
11
import { renderToString } from "react-dom/server";
2-
import { App } from "./App";
3-
import { createProductStore, initialProductState } from "./entities";
4-
import { ProductProvider } from "./entities/products/context/ProductContext";
52
import { RouterProvider } from "./entities/products/context/RouterContext";
6-
import { HomePage, ProductDetailPage, NotFoundPage } from "./pages";
3+
import { HomePage, NotFoundPage, ProductDetailPage } from "./pages";
74
import { UniversalRouter } from "./router/UniversalRouter";
85
import type { PageWithServer } from "./utils/withServerSideProps";
96
import type { StringRecord } from "@hanghae-plus/lib";
7+
import { withProviders } from "./pages/withProviders.tsx";
8+
import type { PropsWithChildren } from "react";
109

1110
type RenderResult = {
1211
head: string;
1312
html: string;
1413
__INITIAL_DATA__: Record<string, unknown>;
1514
};
1615

17-
export const render = async (pathname: string, query: StringRecord): Promise<RenderResult> => {
18-
const renderApp = () => {
19-
return (
20-
<RouterProvider router={router}>
21-
<ProductProvider productStore={createProductStore(initialProductState)}>
22-
<App />
23-
</ProductProvider>
24-
</RouterProvider>
25-
);
26-
};
16+
type ServerParams = Parameters<NonNullable<PageWithServer["ssr"]>>[0];
2717

18+
export const render = async (pathname: string, query: StringRecord): Promise<RenderResult> => {
2819
const router = new UniversalRouter<PageWithServer>();
2920

30-
router.addRoute("/", HomePage);
21+
const App = ({ children }: PropsWithChildren) => {
22+
return <RouterProvider router={router}>{children}</RouterProvider>;
23+
};
3124

32-
router.addRoute("/product/:id/", ProductDetailPage);
33-
router.addRoute(".*", NotFoundPage);
25+
router.addRoute("/", Object.assign(withProviders(HomePage), { ...HomePage }));
26+
router.addRoute("/product/:id/", Object.assign(withProviders(ProductDetailPage), { ...ProductDetailPage }));
27+
router.addRoute(".*", Object.assign(withProviders(NotFoundPage), { ...NotFoundPage }));
3428

3529
router.start(pathname);
3630

37-
type ServerParams = Parameters<NonNullable<PageWithServer["ssr"]>>[0];
38-
const serverParams: ServerParams = { query, params: router.params } as ServerParams;
39-
40-
if (router.target?.ssr) {
41-
const result = await router.target.ssr(serverParams);
42-
const title = (result as unknown as { metadata?: { title?: string } })?.metadata?.title ?? "";
43-
const html = renderToString(renderApp()) ?? "";
44-
const data = (result as unknown as { data?: Record<string, unknown> })?.data ?? {};
31+
const serverParams = { query, params: router.params } as ServerParams;
4532

46-
return {
47-
head: `<title>${title}</title>`,
48-
html,
49-
__INITIAL_DATA__: data,
50-
};
51-
}
33+
const PageComponent = router.target!;
34+
const result = await PageComponent.ssr?.(serverParams);
35+
const metadata = await PageComponent.metadata?.(serverParams);
36+
const html = renderToString(
37+
<App>
38+
<PageComponent productState={result} />
39+
</App>,
40+
);
5241

53-
const metadata = await router.target?.metadata?.(serverParams);
5442
return {
5543
head: `<title>${metadata?.title ?? ""}</title>`,
56-
html: "",
57-
__INITIAL_DATA__: {},
44+
html,
45+
__INITIAL_DATA__: (result ?? {}) as Record<string, unknown>,
5846
};
5947
};

packages/react/src/main.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const enableMocking = () =>
2323
);
2424

2525
function main() {
26-
const renderApp = () => {
26+
const AppContainer = () => {
2727
return (
2828
<RouterProvider router={router}>
2929
<ProductProvider productStore={createProductStore(initialProductState)}>
@@ -46,9 +46,9 @@ function main() {
4646
const hasServerContent = rootElement.innerHTML.trim() !== "";
4747

4848
if (hasSSRData || hasServerContent) {
49-
hydrateRoot(rootElement, renderApp());
49+
hydrateRoot(rootElement, <AppContainer />);
5050
} else {
51-
createRoot(rootElement).render(renderApp());
51+
createRoot(rootElement).render(<AppContainer />);
5252
}
5353
}
5454

packages/react/src/pages/HomePage.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ export const HomePage = withServerSideProps(
7171
return {
7272
products: productsData.products,
7373
categories: categoriesData,
74-
pagination: productsData.pagination,
75-
filters: productsData.filters,
74+
totalCount: productsData.pagination.total,
7675
};
7776
},
7877

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ModalProvider, ToastProvider } from "../components";
2+
import { createProductStore, initialProductState, useLoadCartStore } from "../entities";
3+
import { ProductProvider } from "../entities/products/context/ProductContext";
4+
5+
const CartInitializer = () => {
6+
useLoadCartStore();
7+
return null;
8+
};
9+
10+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
11+
export function withProviders<P extends Record<string, any>>(PageComponent: any) {
12+
return ({ productState, ...props }: P) => {
13+
return (
14+
<ProductProvider productStore={createProductStore(productState ?? initialProductState)}>
15+
<ToastProvider>
16+
<ModalProvider>{PageComponent ? <PageComponent {...props} /> : null}</ModalProvider>
17+
</ToastProvider>
18+
<CartInitializer />
19+
</ProductProvider>
20+
);
21+
};
22+
}

0 commit comments

Comments
 (0)