๐Ÿšง Detected multiple Jotai instances. It may cause unexpected behavior with the default store. ๐Ÿšง

ํ˜œํ˜œยท2023๋…„ 12์›” 1์ผ
0

Error Note

๋ชฉ๋ก ๋ณด๊ธฐ
12/19
post-custom-banner

โ—๋ฌธ์ œ ๋‚ด์šฉ

Next.js ํ”„๋กœ์ ํŠธ์—์„œ Jotai๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€ ๋งŒ๋‚œ ๊ฒฝ๊ณ ...! ๋ง ๊ทธ๋Œ€๋กœ Jotai ์ธ์Šคํ„ด์Šค๊ฐ€ ์ค‘๋ณต๋˜์–ด์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ๊ณ ์ธ ๊ฒƒ ๊ฐ™์•˜๊ณ , ๊ฒฝ๊ณ ๋ฌธ์— ํ•จ๊ป˜ ๋‚˜์˜ค๋Š” github ๋งํฌ๋ฅผ ํƒ€๊ณ  ๋“ค์–ด๊ฐ€์„œ ๋‚ด์šฉ๋„ ์‚ดํŽด๋ดค๋Š”๋ฐ, Context๊ฐ€ ์ค‘์ฒฉ๋˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์–ด์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ๊ณ ๋ผ๊ณ  ๋‚˜์™€ ์žˆ์—ˆ๋‹ค.
ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐ์— Context api๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋‹ค๊ฐ€ Jotai๋ฅผ ๋„์ž…ํ•œ ๊ฑด๋ฐ, ์•„์ง ๊ทธ๋•Œ ์‚ฌ์šฉํ•œ Context๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ๊ฑท์–ด๋‚ด์ง€ ์•Š์•„์„œ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ๋•Œ ์‚ฌ์šฉํ•œ Context ์ฝ”๋“œ๋ฅผ ๋‹ค ๊ฑท์–ด๋‚ด๊ณ  ์ œ๊ฑฐํ–ˆ๋Š”๋ฐ... ๊ณ„์† ๊ฒฝ๊ณ ๊ฐ€ ๋‚˜ํƒ€๋‚ฌ๋‹ค.
github ๋งํฌ๋ฅผ ๋ณด๋ฉด Next.js ์ƒ์œ„ ๋ฒ„์ „์—์„œ ๊ทธ๋ƒฅ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ๊ณ ์ธ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ๋‚ด์šฉ๋„ ์žˆ์–ด์„œ ์ผ๋‹จ ๊ทธ๋ƒฅ ๋„˜์–ด๊ฐˆ๊นŒ ์‹ถ์—ˆ๋Š”๋ฐ ์•„๋ฌด๋ฆฌ ์ƒ๊ฐํ•ด๋„ ๋ญ”๊ฐ€ ์ฐœ์ฐœ...ํ•ด์„œ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ ๋๋‚˜๊ณ  ๋‚จ๋Š” ์‹œ๊ฐ„์— ๋ฌธ์ œ๋ฅผ ๋” ์‚ดํŽด๋ดค๋Š”๋ฐ, ๋“œ๋””์–ด ์–ด๋–ค ๊ฒŒ ๋ฌธ์ œ์ธ์ง€ ๋ฐœ๊ฒฌํ–ˆ๋‹ค!!

layout.tsx

'use client';
import './globals.css';
import type { Metadata } from 'next';
import Providers from '@/components/Provider/providers';

//export const metadata: Metadata = {
//  title: 'Create Next App',
//  description: 'Generated by create next app',
//};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  
  const { getAccessToken } = useAuth();

  useEffect(() => {
    getAccessToken();
  }, []);

  return (
    <html lang="ko">
      <body>
        <Providers>
          {children}
        </Providers>
      </body>
    </html>
  );
}

๊ธฐ์กด์˜ ๋‚ด layout.tsx ํŒŒ์ผ์ด๋‹ค. ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•ด๋„ ๋กœ๊ทธ์ธ์ด ์œ ์ง€๋˜๊ฒŒ๋” ํ•˜๊ณ  ์‹ถ์–ด์„œ layout.tsx์—์„œ ํ† ํฐ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” custom hook์„ ์‹คํ–‰์‹œํ‚ค๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ–ˆ๋Š”๋ฐ, ํ•ด๋‹น ๋กœ์ง ์•ˆ์—์„œ Jotai store์— access token์„ ์ €์žฅํ•˜๋Š” ๋กœ์ง์ด ์žˆ์–ด์„œ ๋ฌธ์ œ์˜€๋‹ค... ์‚ฌ์‹ค ์ด ๋ฃจํŠธ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์— use client๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๋„ ์ •๋ง ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹Œ ๊ฒƒ ๊ฐ™์•„์„œ ๊ณ ๋ฏผ์ด ๋งŽ์•˜๋‹ค... ์•„๋ฌดํŠผ ์ด ํŒŒ์ผ ์•ˆ์—์„œ Jotai๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” Providers๋ฅผ ๊น”์•„์ฃผ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ ๋™์‹œ์— useEffect()๋กœ Jotai๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋กœ์ง์„ ์‹คํ–‰์‹œ์ผœ๋ฒ„๋ฆฌ๋‹ˆ๊นŒ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค.

โš’๏ธ ๋ฌธ์ œ ํ•ด๊ฒฐ

Token.tsx

'use client';
import useAuth from '@/hooks/useAuth';
import { useEffect } from 'react';

function Token() {
  const { getAccessToken } = useAuth();

  useEffect(() => {
    getAccessToken();
  }, []);

  return <></>;
}

export default Token;

ํ† ํฐ์„ ๊ฐ€์ ธ์˜ค๋Š” ๋กœ์ง์„ ์‹คํ–‰์‹œํ‚ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“  ๋‹ค์Œ,

layout.tsx

import './globals.css';
import type { Metadata } from 'next';
import Providers from '@/components/Provider/providers';
import Token from '@/components/Common/Token';

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body>
        <Providers>
          <Token />
          {children}
        </Providers>
      </body>
    </html>
  );
}

๋งŒ๋“  Token ์ปดํฌ๋„ŒํŠธ๋ฅผ layout.tsx์—์„œ importํ•ด์„œ return๋ฌธ ์•ˆ์— ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋‹ˆ use client๋„ ์ง€์šธ ์ˆ˜ ์žˆ์—ˆ๊ณ , metadata๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ์ข‹์•„์กŒ์„ ๋ฟ๋”๋Ÿฌ multiple Jotai instance ๊ฒฝ๊ณ ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค...!

๐Ÿ™‡โ€โ™‚๏ธ ์ฐธ๊ณ ์ž๋ฃŒ

Sharing state with library component
[Next.js] ๋กœ๊ทธ์ธ ๊ตฌํ˜„(Silent Refresh)
โ†’ ์ด ๋ธ”๋กœ๊ทธ์—์„œ ์˜๊ฐ์„ ์–ป์—ˆ๋‹ค๐Ÿ‘€

profile
์‰ฝ๊ฒŒ๋งŒ์‚ด์•„๊ฐ€๋ฉด์žฌ๋ฏธ์—†์–ด๋น™๊ณ 
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€