Skip to content

Persist Storage 가 서버사이드에 존재하지 않아 hydration mismatch 발생하는 버그 해결 #18

@toothlessdev

Description

@toothlessdev

resolve #17

✨ 구현한 기능

서버 사이드에서 Redux Persist 의 WebStorage API 의 부재로 사전렌더링시 오류 발생

  1. 서버 사이드 Storage 임시로 구현 및 서버사이드와 클라이언트 사이드에서 리턴되는 storage 분기
// /src/store/persist/persistStorage.ts
import createWebStorage from "redux-persist/lib/storage/createWebStorage";

const serverSideStorage = () => {
    return {
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        getItem: (_key: string): Promise<string> => {
            return new Promise((resolve) => {
                resolve("{}");
            });
        },
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        setItem: (_key: string, _item: string): Promise<void> => {
            return new Promise((resolve) => {
                resolve();
            });
        },
    };
};

export const persistStorage = typeof window !== "undefined" ? createWebStorage("local") : serverSideStorage();
  1. PersistGate 에서 typeof window === "undefined", 서버에서 실행시 loading props 가 아닌 children props 를 렌더링하도록 수정
// /src/store/persist/PersistGate.ts
if (typeof window === "undefined") return this.props.children;
return this.state.bootstrapped ? this.props.children : this.props.loading;
  1. persistStore 가 자동으로 persist/PERSIST persist/REHYDRATE 액션을 디스패치 하지 않도록 manualPersist 설정
// /src/store/store.ts
export const persistor = persistStore(store, { manualPersist: true } as PersistorOptions);
  1. entry-client.ts 에서 hydration 이후 client 측에서 persist 액션 디스패치 하도록 설정
const root = ReactDOM.hydrateRoot(
    document.getElementById("app") as HTMLElement,
    <BrowserRouter>
        <App isClient={false} />
    </BrowserRouter>,
);

root.render(
    <BrowserRouter>
        <App isClient={true} />
    </BrowserRouter>,
);
export default function App({ isClient }: { isClient: boolean }) {
    useEffect(() => {
        if (isClient) persistor.persist();
    }, [isClient]);

📢 논의하고 싶은 내용

🎸 기타

  • 사전렌더링은 성공하였으나 사전렌더링된 HTML 이 hydration 되기전에 Client Side 에서 재렌더링이 진행되어 Client Side Rendering 으로 전환되는 현상 발생
image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions