NextJS App Route에서 Recoil 사용하기

박재현·2024년 6월 18일
1

NEXT.JS

목록 보기
15/17
post-thumbnail

React를 공부하면서 상태관리를 위해서 Recoil을 사용해왔다.

요즘은 Zustand인가 이게 핫한거 같은데 사용해보지는 않았고, 그냥 필요하면 Recoil을 사용해왔다.

여튼 요즘은 NextJS 14버전을 접하고 나서는 CRA대신 NextJS를 사용해보려고 하고있는데 Recoil을 사용하면 좋겠는데? 싶은 경우가 생겨서 어떻게 NextJS App Route에서 사용할 수 있는지 정리해 두려고 한다.

사실 그리 어려운 내용은 아니긴한데, NextJS App Route에서 기본적으로 Server Component가 Default다.

하지만 Recoil을 사용하려면 Client Component여야하고, 또 RecoilRoot 내부에 있어야한다.

그래서 보통은 React를 사용할때는 index.js나 app.js같이 가장 상위 컴포넌트에서 RecoilRoot를 선언해서 사용했었다.

하지만 NextJS의 가장 상위는 app/layout.tsx 파일인데, 이건 Server Component다.

해당 파일 가장 상단에 "use client" 라는 지시어를 추가하면 바로 에러가 발생하는데, 메타데이터를 사용할 수 없다~ 뭐 그런 에러다.

즉 해당 컴포넌트는 Server Component라는 소리다.

그래서 어떻게 하면 될까 생각해보니, Client Component는 Server Component에서 아무렇지 않게 Import해서 사용할 수 있다.

따라서 app/layout.tsx 파일에 RecoilRoot를 포함하고 있는 ClientCompopnt를 불러와서 사용하면 된다.

Before

// app/layout.tsx

export default function RootLayout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <html lang="en">
            <body className={inter.className}>
                {children}
            </body>
        </html>
    );
}

After

// app/layout.tsx

export default function RootLayout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <html lang="en">
            <body className={inter.className}>
                <RecoilRootWrapper>{children}</RecoilRootWrapper>
            </body>
        </html>
    );
}

// component/recoil-wrapper.tsx
"use client";

import { RecoilRoot } from "recoil";

export default function RecoilRootWrapper({
    children,
}: {
    children: React.ReactNode;
}) {
    return <RecoilRoot>{children}</RecoilRoot>;
}

아! 추가적으로 Recoil을 이용해서 사용하려는 상태변수가 브라우저가 리프레시가 되어도 값이 유지되도록 하고 싶다면 recoil-persist 이라는 패키지를 사용하면 된다.

  1. npm install recoil-persist 을 이용해서 설치

  2. atom을 통해 state를 관리하는 파일에 내부에 아래와 같이 recoil-persist를 import해주고 persistAtom을 선언.

import { recoilPersist } from 'recoil-persist';

const { persistAtom } = recoilPersist();
  1. 브라우저가 리프레쉬 되어도 상태가 유지되길 원하는 atom 오브젝트에 아래와 같이 effects_UNSTABLE을 추가한다.
export const levelState = atom<0 | 1 | 2>({
    key: "levelState",
    default: 0,
    effects_UNSTABLE: [persistAtom],
});

참고로 recoil-persist가 내부적으로 localstorage를 사용한다고 하는데, localstorage에 등록되기 민감한 정보라면 다른 방법을 고려하는게 좋아보인다.

profile
기술만 좋은 S급이 아니라, 태도가 좋은 A급이 되자

0개의 댓글

관련 채용 정보