-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SSR][NextJS] Duplicate atom key during development and during production build in nextjs #733
Comments
Also mentioned in: |
Has this been solved? I'm having the same issue. |
@leonardomgt I was not able to solve this yet. @drarmstr Tagging you as you seem to be a main contributor to this project, any chance you could have look at this? Thanks! |
@janus-reith - Sorry, I'm not very familiar with Next.JS or SSR. |
Next.js has a concept of Pages. Imagine an SPA with multiple entry points, like an Admin and a Client App, both importing a module that declares a Recoil In development, when a file is changed, Next.js re-builds the relevant page entry file. Basically, I can't think of a solution to this problem besides providing a configuration setting to disable this check/warning. A zero config alternative might be tempting. E.g. relying on |
Related to #247 |
Thanks @drarmstr for the response nonetheless, and thanks @alexilyaev for the detailed description. Regarding the multiple entry points, I wonder if this could be worked around by some more advanced tracing logic to distinguish actual redeclaration of the key from the same code being executed again using the callsite? |
Me to for this issue. |
Hey guys, any update on this issue? Has anybody come up with a workaround? Thanks! |
Ok guys, here's a temporary "solution" via a webpack "plugin" that kills the from... function registerNode(node) {
if (nodes.has(node.key)) {
....code
console.warn(message); // @oss-only
}
....code
} to: function registerNode(node) {
if (nodes.has(node.key)) {
....code
(!process.env.__NEXT_PROCESSED_ENV && !process.env.SILENCE_RECOIL_DUPE_WARNING) && console.warn(message); // @oss-only
}
....code
} ✅ Am I desperate? // feel free to replace these
const fs = require('promise-fs')
const path = require('path')
/**
Webpack plugin that modifies /node_modules/recoil/[...]/recoil.js
adding process.env conditionals before the registerNode/duplicate key warning log
**/
{
apply: (compiler) => {
return compiler.hooks.run.tapAsync(
"SilenceRecoilDupeWarningBeforeCompile",
async (compilation, callback) => {
const SILENCING_VARS = [
"__NEXT_PROCESSED_ENV",
"SILENCE_RECOIL_DUPE_WARNING",
];
const silenceModule = async (module) => {
// target recoil module & path (Adjust for your own project) 👈 mono repo setup
const recoilModulePath = path.join(
process.cwd(),
"..",
`/node_modules/${module}`
);
console.log(`Disabling ${recoilModulePath} warnings`);
// read the source module
const recoilSource = await fs.readFile(recoilModulePath, "utf8");
// any of these will silence the warning
const conditionalString = `(${SILENCING_VARS.reduce(
(condStr, envVar) => {
condStr = [...condStr, `!process.env.${envVar}`];
return condStr;
},
[]
).join(" && ")}) &&`;
// regex and replace function
const duplicateWarningRegex = /(if \(nodes\.has\(node\.key\)\) \{.*?)(console\.warn\(message\)\;)(.*?\})/gs;
const duplicateWarningReplace = (str, $1, $2, $3) => {
if ($1 && $3) {
return `${
$1 ? $1.replace(conditionalString, "") : ""
}${conditionalString} console.warn(message);${$3}`;
}
return str;
};
// modify the recoil source file
const modifiedRecoilSource = recoilSource.replace(
duplicateWarningRegex,
duplicateWarningReplace
);
// overwrite the recoil module - cause you can 🤷♂️
await fs.writeFile(recoilModulePath, modifiedRecoilSource, "utf8");
};
try {
const TARGET_RECOIL_MODULES = [
"recoil/cjs/recoil.js",
"recoil/es/recoil.js",
"recoil/umd/recoil.js",
];
for (let m = 0; m < TARGET_RECOIL_MODULES.length; m++) {
const currentModule = TARGET_RECOIL_MODULES[m];
await silenceModule(currentModule);
}
console.log("Disabled recoil duplicate key warning (hopefully).");
callback();
} catch (error) {
console.log("SilenceRecoilDupeWarningBeforeCompile", error);
callback();
}
}
);
};
} Hopefully this enthusiasm sparks a proper solution... 👍 UPDATE: less invasive solution for nextjs here |
I am reproducing this on my Next.js app. I only do SSR when running locally in dev mode, otherwise in production - I export static files via SSG. From what I can tell, this is just a warning and safe to ignore. Even though I'm a newbie to Recoil - it seems to be working 😨? I actually only see the output in the server logs... not the browser. Although the output is annoying, I just want to make sure this isn't a blocker in using Recoil. Can I just ignore the output? Or is this issue about actual broken functionality? |
You can ignore the warning output (if you can bare it), functionality is not affected (We have a few sites in production working just fine) :( |
I'm very eager to start using Recoil in my applications, but errors like this make me wary of adopting. Any official update on this? I'd prefer a solution that doesn't involve modifying the source code in node_modules. |
I feel you, I love recoil too much (specially on Nextjs), so I've taken a leap of faith that the staff will do something about it since SSR environments are here to stay and we have very complex production apps running beautifully with it. Fingers crossed 🙏🏼 |
@juanpprieto I've found a less invasive method that relies on the intercept-stdout package. Add the following to
This way I don't have to modify the source code in node_modules. Do you see any downsides to this approach? |
Hey @R-Bower! On paper this seems 1000 times less invasive than my hack! I will test at my end and let you know! — Thanks for the heads up! |
The error still shows on in-browser hot reloads. Not sure if there's a way to suppress those other than the chrome console regex filter. |
Yes, This why I ended up doing the hack I did unfortunately. If anyone knows another option to try for muting browser warnings I'd love to hear and try them. Thanks! |
@R-Bower think i may have found a cleaner way to kill recoil browser warnings.
const memoize = (fn) => {
let cache = {};
return (...args) => {
let n = args[0];
if (n in cache) {
return cache[n];
}
else {
let result = fn(n);
cache[n] = result;
return result;
}
}
}
// ignore in-browser next/js recoil warnings until its fixed.
const mutedConsole = memoize((console) => ({
...console,
warn: (...args) => args[0].includes('Duplicate atom key')
? null
: console.warn(...args)
}))
global.console = mutedConsole(global.console);
const intercept = require("intercept-stdout")
// safely ignore recoil stdout warning messages
function interceptStdout(text) {
if (text.includes('Duplicate atom key')) {
return ''
}
return text
}
// Intercept in dev and prod
intercept(interceptStdout) Let me know if this works for you! |
@juanpprieto It works! Thanks :) |
This hangs when I start the server on next.js |
we got there in the end <3 |
Just faced this issue... Came here and saw this patch 0.7.6 released yesterday. Am I lucky? 😆 |
@wfortin is correct. Recoil 0.7.6 with |
const intercept = require('intercept-stdout'); // safely ignore recoil stdout warning messages intercept(interceptStdout); |
I've been waiting a year for this answer!!!!!! |
how can i do this with Vite? on Vite it requires that the env variables should start with |
I was thinking this same thing. |
@hamtarodev @satokoki645 The recoil changelog will help you, as of 6/10/22: https://yarnpkg.com/package/recoil |
@ThomasCarstens Thanks! // configs/recoil.ts
import { RecoilEnv } from 'recoil';
RecoilEnv.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED = false; // App.tsx
import './configs/recoil';
function App() {
return (
<RecoilRoot>
{ ... }
</RecoilRoot>
);
} |
Thanks to this, I was able to remove the console log from nextJS. This is my code /** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
env: {
// @see https://github.com/facebookexperimental/Recoil/issues/2135#issuecomment-1362197710
RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED: "false",
}
};
module.exports = nextConfig; |
solved problem. in my case
lovely thanks. |
- atomKey 가 고유한데 해당 이슈 발생해서 찾아보니 recoil 0.7.6 이슈 같음 https://stackoverflow.com/questions/65506656/recoil-duplicate-atom-key-in-nextjs facebookexperimental/Recoil#733 (comment)
* [feat] Login UI 구현 * [feat] ContentLayout UI 구현 - 로그인 화면, 온보딩과 같은 싱글 컨텐츠 레이아웃 UI 구현 * [feat] LoginPage UI 구현 * [feat] signin api 기능 및 msw 구현 * [feat] google oauth 로그인 후 헤더 UI 구현 * [feat] recoil 관련 storybook 설정 * [feat] 커먼성 UserInfo UI 구현 - User 의 정보를 나타내는 UserInfo 컴포넌트 구현 * [feat] 로그인 성공후 유저 정보를 클릭 시 나타나는 UserMenu UI 구현 * [feat] User UI 클릭 시 유저메뉴 보이는 기능 구현 * [feat] recoil localstorage effect 기능 구현 - 로그인 성공시 해당 user 정보를 localstorage 에 저장하여 영구적으로 사용할 수 있도록 설정 * [feat] google oauth redirect 기능 구현 * [fix] 🐛 nextjs Hydration failed error 수정 - recoil effect 로 localstorage 에 user 값이 있냐 없냐에 따라 로그인 상태 여부를 판단하는데 해당 기능을 추가할 때 Hydration failed 에러 발생 => 유추한 결과 window undefined 를 판단하는데 이때 초기 렌더링 UI 와 달라 발생하는 거 같음 - 해당 URL 참고하여 수정 https://stackoverflow.com/questions/71706064/react-18-hydration-failed-because-the-initial-ui-does-not-match-what-was-render/71797054#71797054 * [feat] api 없는 로그아웃 기능 구현 * [fix] 🐛 recoil 0.7.6 Duplicate atom key error 수정 - atomKey 가 고유한데 해당 이슈 발생해서 찾아보니 recoil 0.7.6 이슈 같음 https://stackoverflow.com/questions/65506656/recoil-duplicate-atom-key-in-nextjs facebookexperimental/Recoil#733 (comment) * [refactor] type 수정 * [feat] env-sample 에 NEXT_PUBLIC_GOOGLE_CLIENT_ID 형식 추가 * [chore] chromatic 배포를 위한 환경설정 값 추가 * [chore] 실수로 올린 .env 파일 제거 * [chore] 실수로 변경한 config 설정 수정 * [refactor] 코드리뷰 적용 - auth Type 수정 - resetUser 네이밍 수정 - UserInfo 컴포넌트 default type 수정 - 불필요한 코드 제거 * [refactor] login page 구조 변경
Just because of this issue I had to move to Jotai. disabling the Duplicate key checker is not a fix. now, recoil won't check for duplicate keys. |
I tried all the above methods but they didn't solve my problem. Every time I refresh the page, I report an error, so I rudely used the following method to solve the problem console.error = (messages, ...rest) => {
if (messages?.message?.includes("Duplicate atom key")) {
return
}
console.warn(messages, ...rest)
} |
* chore: vite 초기 설정 * docs: 기능 요구 사항 반영하여 구현 목록 작성 Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com> * chore: github page 자동 배포 설정 * chore: storybook 설치 및 자동배포 설정 * test: product item 컴포넌트 스토리북 테스트 추가 * feat: product item 컴포넌트 뼈대 구현 * chore: styled-components 및 해당 타입 설치 * feat: product item 컴포넌트 스타일 구현 * test: product item 컴포넌트 스타일북 케이스 추가 * feat: product item type 별도로 분리 * feat: CartController 컴포넌트 구현 및 적용 * test: CartController 스토리 추가 * refactor: ProductItem 스타일 높이 변경 및 배경 색상 제거 * refactor: 사용하지 않는 App, index 스타일 제거 * chore: svg 이미지 파일 추가 및 타입 설정 * feat: global style 적용하여 기본 스타일링 reset * chore: svg 파일 타입 컴포넌트로 지정 * feat: Header 컴포넌트 스타일 적용하여 구현 * test: Header 컴포넌트 스토리 테스트 추가 * refactor: 프로젝트 title 변경 * feat: style theme 적용 * test: header 컴포넌트 스토리에 providers 적용 * fix: globalStyle 오탈자 수정 * test: ProductItem 컴포넌트 스토리북에 providers 적용 * chore: 배포 중 eslint 적용하지 않도록 설정 * fix: 배포시 빌드 버그 수정 * fix: 사용하지 않는 라이브러리 import 제거 * chore: react-router-dom 설치 * feat: react router dom을 위한 공통 레이아웃 구현 및 적용 * fix: base url 버그 수정 * fix: storybook 테스트를 위한 router-dom providers에 추가 * chore: recoil 설치 * feat: 상품 리스트 mock 데이터 생성 * feat: recoil root 적용 및 providers에 추가 * feat: Home 컴포넌트 구현 및 상품 리스트를 mock api로 구현 * feat: cart list 상태로 관리 및 장바구니 등록 버튼 클릭시 상태 변경 구현 * feat: 장바구니 리스트 수량 조절 기능 구현 * fix: useCart 커스텀 훅 mockAPI 통신 순서 변경 * fix: CartController 컴포넌트 자체로 갖고 있던 quantity 상태 제거 * refactor: useCart 커스텀훅 반복되는 로직 추상화 * feat: 반응형 ui 적용 * refactor: CartController 컴포넌트 높이 등 세부 스타일링 수정 * feat: mockApi 적용하여 장바구니 아이템 local storage에 등록 구현 * feat: mockApi 이용하여 장바구니 업데이트 및 local storage 등록 * feat: 상품 리스트 local storage 등록 및 로딩 시 불러오기 구현 * feat: mockApi 이용하여 장바구니 아이템 삭제 기능 구현 * fix: 컴포넌트 수정으로 인한 storybook 수정사항 적용 * refactor: 사용하지 않는 지역변수 제거 * docs: 기능 요구사항 문서 최신화 * refactor: 기본 이미지를 고양이에서 다른 이미지로 변경 * refactor: atom 모듈화 * fix: 수량이 100개 이상 설정되는 문제 수정 * docs: 기능 목록 요구사항 최신화 * docs: readme 작성 * style: 불필요한 코드 제거 및 코드 간격 조정 등 * feat: 데이터 처리 중 오류 발생 시 콘솔에 결과가 출력되는 기능 구현 * Update readme.md * Update readme.md * refactor: html lang을 en 에서 ko 로 변경 * refactor: 과도한 래핑 함수 제거 * refactor: 가독성 개선을 위해 quantity 삼항연산자 분리 * style: jsx self-closing element 적용 * style: 불필요한 주석 제거 * refactor: 검색한 카트의 수량을 nullish coalescing operator으로 접근하도록 개선 * refactor: 타입 import 방식 변경 - Type-Only Imports and Exports 로 변경 - https://www.typescriptlang.org/ko/docs/handbook/release-notes/typescript-3-8.html * refactor: import * as S from ... 표기법 제거 * refactor: 신규 장바구니 아이템 추가 전 검사하는 로직 개선 * style: 불필요한 Fragment 제거 * refactor: addCart에서 이미 있는 장바구니 아이템이 발견되는 경우 반환되는 로직을 개선 * style: 주석 스타일 개선 * refactor: 장바구니 페이지 품목 임시 표시용 텍스트 스타일 변경 * chore: storyvook v6 => v5.3.10으로 다운그레이드 * chore: 미사용 패키지 제거 * refactor: newCartItem을 타입으로 강제하도록 개선 * refactor: nested object 의 프로퍼티 값을 수정하기 위한 새로운 함수 구현 - map 함수를 제거 * chore: recoil-persist 설치 * refactor: mockApi 제거 - recoil-persist를 활용하여 장바구니 리스트를 세션 스토리지에서 관리 - 추후 msw로 이전하기 위한 기초 작업 * refactor: ProductList 컴포넌트 추가 - useRecoilValueLoadable에서 데이터를 받아오도록 개선 * refactor: 불필요한 커스텀훅 제거 * refactor: 장바구니 갯수를 selector로 계산하도록 개선 * refactor: 함수명 변경 * refactor: 장바구니 수량 조회 로직 개선 - atoms selector로 조회 * fix: vite 환경에서의 Duplicate atom key 에러 해결 facebookexperimental/Recoil#733 (comment) * fix: selector 버그 수정을 위해 원상 복구 * refactor: recoil-persist 제거 - recoil 상태 유지를 하지 않는 것으로 계획 변경 * chore: msw 설치 및 기본 세팅 * refactor: 상품 목록을 fetch에 연결 및 msw 모킹 구현 * chore: react-error-boundary 설치 * refactor: 상품 리스트 수신 에러 핸들링 * refactor: 장바구니 목록을 msw로 mocking * refactor: 신규 장바구니 추가 fetch 추가 및 msw mocking 구현 * refactor: 삭제 fetch 구현 (msw) * refactor: 장바구니 아이템 수량 변경 fetch 코드 구현 및 msw mocking * refactor: mockData 이미지 주소를 http => https 변경 * fix: 배포시 이미지가 뜨지 않는 문제 수정 * fix: 이미지 요청이 필터링 되는 문제 수정 * refactor: api 계층 분리 * fix: 이미지 버그 수정 - 기존에 사용한 임시 파일이 https가 아닌 http로 변환되는 문제가 있었음. * style: 불필요한 코드 제거 * refactor: 불필요한 코드 제거 --------- Co-authored-by: ukkodeveloper <ukkodeveloper@gmail.com>
* chore: vite 초기 설정 * docs: 기능 요구 사항 반영하여 구현 목록 작성 Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com> * chore: github page 자동 배포 설정 * chore: storybook 설치 및 자동배포 설정 * test: product item 컴포넌트 스토리북 테스트 추가 * feat: product item 컴포넌트 뼈대 구현 * chore: styled-components 및 해당 타입 설치 * feat: product item 컴포넌트 스타일 구현 * test: product item 컴포넌트 스타일북 케이스 추가 * feat: product item type 별도로 분리 * feat: CartController 컴포넌트 구현 및 적용 * test: CartController 스토리 추가 * refactor: ProductItem 스타일 높이 변경 및 배경 색상 제거 * refactor: 사용하지 않는 App, index 스타일 제거 * chore: svg 이미지 파일 추가 및 타입 설정 * feat: global style 적용하여 기본 스타일링 reset * chore: svg 파일 타입 컴포넌트로 지정 * feat: Header 컴포넌트 스타일 적용하여 구현 * test: Header 컴포넌트 스토리 테스트 추가 * refactor: 프로젝트 title 변경 * feat: style theme 적용 * test: header 컴포넌트 스토리에 providers 적용 * fix: globalStyle 오탈자 수정 * test: ProductItem 컴포넌트 스토리북에 providers 적용 * chore: 배포 중 eslint 적용하지 않도록 설정 * fix: 배포시 빌드 버그 수정 * fix: 사용하지 않는 라이브러리 import 제거 * chore: react-router-dom 설치 * feat: react router dom을 위한 공통 레이아웃 구현 및 적용 * fix: base url 버그 수정 * fix: storybook 테스트를 위한 router-dom providers에 추가 * chore: recoil 설치 * feat: 상품 리스트 mock 데이터 생성 * feat: recoil root 적용 및 providers에 추가 * feat: Home 컴포넌트 구현 및 상품 리스트를 mock api로 구현 * feat: cart list 상태로 관리 및 장바구니 등록 버튼 클릭시 상태 변경 구현 * feat: 장바구니 리스트 수량 조절 기능 구현 * fix: useCart 커스텀 훅 mockAPI 통신 순서 변경 * fix: CartController 컴포넌트 자체로 갖고 있던 quantity 상태 제거 * refactor: useCart 커스텀훅 반복되는 로직 추상화 * feat: 반응형 ui 적용 * refactor: CartController 컴포넌트 높이 등 세부 스타일링 수정 * feat: mockApi 적용하여 장바구니 아이템 local storage에 등록 구현 * feat: mockApi 이용하여 장바구니 업데이트 및 local storage 등록 * feat: 상품 리스트 local storage 등록 및 로딩 시 불러오기 구현 * feat: mockApi 이용하여 장바구니 아이템 삭제 기능 구현 * fix: 컴포넌트 수정으로 인한 storybook 수정사항 적용 * refactor: 사용하지 않는 지역변수 제거 * docs: 기능 요구사항 문서 최신화 * refactor: 기본 이미지를 고양이에서 다른 이미지로 변경 * refactor: atom 모듈화 * fix: 수량이 100개 이상 설정되는 문제 수정 * docs: 기능 목록 요구사항 최신화 * docs: readme 작성 * style: 불필요한 코드 제거 및 코드 간격 조정 등 * feat: 데이터 처리 중 오류 발생 시 콘솔에 결과가 출력되는 기능 구현 * Update readme.md * Update readme.md * refactor: html lang을 en 에서 ko 로 변경 * refactor: 과도한 래핑 함수 제거 * refactor: 가독성 개선을 위해 quantity 삼항연산자 분리 * style: jsx self-closing element 적용 * style: 불필요한 주석 제거 * refactor: 검색한 카트의 수량을 nullish coalescing operator으로 접근하도록 개선 * refactor: 타입 import 방식 변경 - Type-Only Imports and Exports 로 변경 - https://www.typescriptlang.org/ko/docs/handbook/release-notes/typescript-3-8.html * refactor: import * as S from ... 표기법 제거 * refactor: 신규 장바구니 아이템 추가 전 검사하는 로직 개선 * style: 불필요한 Fragment 제거 * refactor: addCart에서 이미 있는 장바구니 아이템이 발견되는 경우 반환되는 로직을 개선 * style: 주석 스타일 개선 * refactor: 장바구니 페이지 품목 임시 표시용 텍스트 스타일 변경 * chore: storyvook v6 => v5.3.10으로 다운그레이드 * chore: 미사용 패키지 제거 * refactor: newCartItem을 타입으로 강제하도록 개선 * refactor: nested object 의 프로퍼티 값을 수정하기 위한 새로운 함수 구현 - map 함수를 제거 * chore: recoil-persist 설치 * refactor: mockApi 제거 - recoil-persist를 활용하여 장바구니 리스트를 세션 스토리지에서 관리 - 추후 msw로 이전하기 위한 기초 작업 * refactor: ProductList 컴포넌트 추가 - useRecoilValueLoadable에서 데이터를 받아오도록 개선 * refactor: 불필요한 커스텀훅 제거 * refactor: 장바구니 갯수를 selector로 계산하도록 개선 * refactor: 함수명 변경 * refactor: 장바구니 수량 조회 로직 개선 - atoms selector로 조회 * fix: vite 환경에서의 Duplicate atom key 에러 해결 facebookexperimental/Recoil#733 (comment) * fix: selector 버그 수정을 위해 원상 복구 * refactor: recoil-persist 제거 - recoil 상태 유지를 하지 않는 것으로 계획 변경 * chore: msw 설치 및 기본 세팅 * refactor: 상품 목록을 fetch에 연결 및 msw 모킹 구현 * chore: react-error-boundary 설치 * refactor: 상품 리스트 수신 에러 핸들링 * refactor: 장바구니 목록을 msw로 mocking * refactor: 신규 장바구니 추가 fetch 추가 및 msw mocking 구현 * refactor: 삭제 fetch 구현 (msw) * refactor: 장바구니 아이템 수량 변경 fetch 코드 구현 및 msw mocking * refactor: mockData 이미지 주소를 http => https 변경 * fix: 배포시 이미지가 뜨지 않는 문제 수정 * fix: 이미지 요청이 필터링 되는 문제 수정 * refactor: api 계층 분리 * fix: 이미지 버그 수정 - 기존에 사용한 임시 파일이 https가 아닌 http로 변환되는 문제가 있었음. * style: 불필요한 코드 제거 * refactor: 불필요한 코드 제거 * refactor: 버튼 디자인 개선 * refactor: 헤더 디자인 개선 * feat: 장바구니 기본 html 뼈대 작업 * feat: 장바구니 컴포넌트 뼈대 추가 * refactor: 장바구니 아이템 기본 디자인 추가 * refactor: 장바구니 목록 디자인 뼈대 구현 * chore: eslint 규칙 추가 * refactor: 테마의 색상을 nested 객체로 수정 * refactor: 변수명 변경 - Column => Col - Cart => CartItem * fix: 오탈자 수정 * refactor: CartList 컴포넌트 분리 * feat: 구매 박스 모듈화 및 기본 디자인 적용 * refactor: 장바구니 페이지 디자인 개선 작업 - 구매 박스 모듈화 - 장바구니 페이지 내 간격 및 구조 개선 등 * fix: 브랜치 변경으로 인해 자동 배포가 되지 않던 문제 해결 * refactor: fetchAddCart 로직 개선 * refactor: useCart 코드 정리 - 일부 코드 모듈화 - 과도한 연산을 요구하는 함수의 역할을 이전 등 * feat: 장바구니 아이템이 선택됐는지 확인할 수 있는 체크용 프로퍼티 추가 - 기본 값으로 참(체크됨) 처리 * feat: 장바구니 페이지에서 아이템을 직접 삭제할 수 있는 기능 추가 * feat: 모든 아이템이 선택되었을 때 전체 선택이 자동으로 체크 처리 되는 기능 구현 * feat: 장바구니 아이템 구매여부 체크기능 구현 * fix: storybook 배포 버그 문제 수정 - 프로퍼티 변경 반영 * feat: 장바구니 리스트 전체 선택/해제 기능 구현 * feat: 장바구니 리스트에서 현재 몇 개의 상품이 선택됐는지 확인하는 기능 구현 * feat: 장바구니 결제 금액 계산기 구현 * refactor: 장바구니 리스트와 구매 박스 styled-components 추가 적용 * feat: 장바구니 리스트가 비어있을 때 대응하는 페이지 추가 * test: 스토리북에서 장바구니 아이템을 아주 많이 추가했을 때의 케이스를 추가 * feat: 장바구니 페이지에 반응형 시스템 추가 * refactor: 숫자 표기가 1,000단위에서 끊기게 수정 * refactor: 디자인 개선 - 결제 텍스트 간격 개선 - 휴지통에 커서 효과 적용 * feat: 물품 삭제 시 확인 문구 출력하는 기능 추가 * refactor: recoil 상태관리에 필요한 selectors 구조 개선 * feat: 상품에 hover 효과 적용 * feat: 상품에 스켈레톤 효과 적용 * feat: 상품 정보를 출력할 모달 추가 * feat: 상품 정보를 출력할 모달 구현 및 디자인 완료 * feat: 상품에 장바구니 수량이 뜨는 디자인 기능 구현 * feat: 장바구니에서 빈 공간을 눌렀을 때의 상호작용 기능 추가 - 장바구니 쉽게 체크하기 - 장바구니 전체 쉽게 체크하기 * feat: 선택 삭제 기능 구현 * refactor: 상품 조회 모달 디자인 개선 * refactor: 장바구니 수량 조절 디자인 개선 * refactor: Modal 컴포넌트의 styled 모듈화 * refactor: 상품 모달 코드 구조 개선 - styled 모듈화 * refactor: selectFamily를 활용하여 특정 상품의 장바구니 수량을 얻을 수 있도록 로직 개선 * refactor: selectFamily를 활용하여 특정 상품의 장바구니 수량을 수정할 수 있는 로직 구현 * refactor: updateCartListQuantitySelector에서도 fetch가 되도록 개선 및 기존 코드 제거 * refactor: 불필요한 함수 제거 * refactor: 함수명 변경 - updateCartListQuantitySelector => updateCartItemQuantitySelector * refactor: 장바구니 아이템을 추가하는 로직 개선 * refactor: 장바구니 아이템을 삭제하는 로직 개선 * refactor: 장바구니 아이템 수량 조절기로 삭제하는 로직 복구 * refactor: 선택된 장바구니 아이템을 삭제하는 기능 로직 개선 * refactor: 장바구니 구매 체크박스 선택 로직 개선 * refactor: 장바구니 전체 선택 기능 로직 개선 - 커스텀훅 완전 제거 * fix: 배포 버그 수정 * chore: 스토리북 배포 설정 수정 * fix: 스토리북 중복 키 문제 수정 * Update readme.md * style: 전체 프로젝트 prettier 적용 * fix: 병합 충돌 문제 해결 * refactor: 불필요한 코드 제거 * refactor: 카트 아이콘 코드 개선 * refactor: 상품 목록을 요청하는 기능을 모듈화 하기 위해 컴포넌트로 분리 * refactor: 불필요한 변수 제거 * refactor: 모든 장바구니 아이템 체크 여부 확인 로직 개선 * refactor: useRecoilCallback를 활용한 상태 업데이트 로직 개선 - useSetRecoilState에서 인자를 반드시 넘겨줘야 하는 문제를 해결하기 위해 useRecoilCallback을 사용 - https://recoiljs.org/docs/api-reference/core/useRecoilCallback/ --------- Co-authored-by: ukkodeveloper <ukkodeveloper@gmail.com>
It's said, I know. |
Both during local development and also when building a production build, I’m getting a duplicate atom key for each key and each page using it after the first one.
I put together a quick sandbox to demonstrate the issue:
https://codesandbox.io/s/flamboyant-sea-tqlky
The errors show up in the build log, a quick way to test is using the integrated vercel deployment button.
Looking at the default nextjs example, I can‘t spot any special settings there that would prevent whatever duplication is going on from happening: https://github.com/vercel/next.js/tree/canary/examples/with-recoil
That example however only makes use of recoil state on one page.
The text was updated successfully, but these errors were encountered: