묻고 답해요
140만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Next + React Query로 SNS 서비스 만들기
프로필 부분 getUser.ts Error가 반환되지 않는 이유를 모르겠습니다.
import { QueryFunction } from "@tanstack/react-query"; import { User } from "@/model/User"; const getUser: QueryFunction<User, [string, string]> = async ({ queryKey }) => { const [_1, username] = queryKey; const res = await fetch(`http://localhost:9090/api/users/${username}`, { next: { tags: ["users", username], }, cache: "no-store", }); console.log("res.ok : ", res.ok); if (!res.ok) { throw new Error("해당 유저 정보를 불러오지 못 했습니다."); } return res.json(); }; export default getUser; mocks>handler.ts에 없는 username을 url에 입력해도 res.ok로 떠서 if문을 그냥 통과해버립니다.혹시 제가 놓치는 부분이 있는걸까요?
-
미해결Next + React Query로 SNS 서비스 만들기
prefetchQuery 관련 질문
prefetchQuery 서버컴포넌트에서 데이터를 한번 불러오면, 정상적으로 불러왔는지 확인할 수 있나요??서버 컴포넌트에서 prefetchQuery한 다음에 클라이언트컴포넌트에서 useQuery로 불러오게 되면(queryKey 동일) 이미 데이터가 저장 되어 있는거로 알고 있는데,console.log를 찍어보게 되면, undefined가 뜬 다음에 데이터가 호출 됩니다.prefetchQuery가 정상적으로 동작 안하는게 아닌가 싶습니다. export default function TestClient() { const { data } = useQuery({ queryKey: ['typeData'], queryFn: getTypeData, }); console.log(typeData); ...export default async function TestServer() { const queryClient = new QueryClient(); await queryClient.prefetchQuery({ queryKey: ['typeData'], queryFn: getTypeData }); const dehydratedState = dehydrate(queryClient); return ( <> <HydrationBoundary state={dehydratedState}> <TestClient /> </HydrationBoundary> </> ); }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
리액트 설치에 대해 궁금한 점이 있습니다.
현재 리액트부분을 시작했는데 리액트를 설치할때 yarn add next@12.1.0 react@17.0.2 react-dom@17.0.2 --exact이러한 명령어를 사용하는데 이렇게 설치하고 나니 제가 알고있는 폴더들이나 내용이 좀 다르더라구요. 제가 알고있는 건 npx create-react-app ./ 이러한 명령어로 리액트를 설치했는데 이거와 전혀 다른 명령어 인가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
yarn 설치가 되지않습니다.
node.js와 npm은 --version을 이용하니 버전이 나오는데 yarn은 버전이 나오지 않아 npm install -g yarn 이라는 명령어를 하니 이미지처럼 에러가 나옵니다.
-
해결됨Next + React Query로 SNS 서비스 만들기
인터셉팅 라우터가 signup에는 적용이 안되는 문제
login은 인터셉팅 라우터가 잘 되는데,signup은 (.)i로 인터셉팅이 안되고 버튼 클릭을 하면 그냥 i/flow/signup/page.tsx로만 보여지는 문제가 있습니다. 왜 signup은 인터셉팅 라우터가 작동이 안되는 것일까요?? 경로는 이렇게 잘 설정되어있고 안에 파일 내용은 아래와 같습니다. 아래는 @modal/(.)i/flow/signup/page.tsx아래는 i/flow/signup/page.tsx홈 버튼 링크는 아래와 같이 되어있습니다.혹시 제가 빠뜨린 무엇이 있을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션11 eslint 설치
eslint 설치 시 3개 중에 마지막 3번째를 선택하라고 하는데 저는 선택지가 2개만 나옴니다. 2번째를 선택해서 설치해도 되나요?
-
미해결Next + React Query로 SNS 서비스 만들기
http://localhost:3000/api/auth/session 500에러
안녕하세요 선생님 로컬에서 locallhost:3000/api/auth를 호출하면 500에러가 발생합니다.* 참고: 1. useSession()은 모두 클라이언트 컴포넌트에만 적용했습니다. 2. 원인을 찾아보다가 예전 선생님 답변해주신 서버 컴포넌트에서 세션props로 받아스라고 하신거 참고해서 그렇게 수정해도 동일하게 발생합니다.3. 비슷한 질문에 쿠키랑 다 없앤뒤 잘됐다는것도 보고 다제거해봤지만 동일하게 발생했습니다.4. .next, node_module 다 제거후 새로 깔거나, 빌드를 새로 하거나 테스트도 해보았습니다.5. 브라우저 껐다키고, 컴퓨터 재부팅도 해보았습니다.6. 선생님의 깃코드를 가져다 쓰기도 해보았습니다.빌드 한후에 npm run start로 했을땐 정상적으로 나오는데 로컬에서만 발생합니다. /src/auth.tsimport NextAuth from "next-auth" import Credentials from "next-auth/providers/credentials" export const { handlers, signIn, signOut, auth } = NextAuth({ pages: { signIn: '/login', newUser: '/signup', }, providers: [ Credentials({ credentials: { id: {}, password: {}, }, authorize: async (credentials) => { try { const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(credentials), }) console.log(authResponse.ok, '-----------------------------authResponse.ok'); if (!authResponse.ok) { return null; } let user = await authResponse.json(); console.log(user, '--------------------------------'); return { ...user, email: user.id, name: user.nickname, image: user.image, } } catch (err) { console.error('로그인 에러', err); } }, }), ], }).envAUTH_SECRET=WKFOJhbw7gZOYXumT66CwwKtDZ9YsalV8qMRx134Uc8= AUTH_TRUST_HOST=http://localhost:3000.env.localNEXT_PUBLIC_API_MOCKING=enabled NEXT_PUBLIC_MODE=local NEXT_PUBLIC_BASE_URL=http://localhost:9090 NEXTAUTH_URL=http://localhost:3000 /src/app/layout.tsximport type { Metadata, Viewport } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; import { MSWComponent } from './_component/MSWComponent'; import AuthSession from './_component/AuthSession'; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { title: { template: '%s | MBTI', default: 'MBTI가 어떻게 되세요?', }, description: "MBTI로 찾는 내 연인", }; export const viewport: Viewport = { width: 'device-width', initialScale: 1, maximumScale: 1, userScalable: false, // Also supported by less commonly used // interactiveWidget: 'resizes-visual', } export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="en"> <body className={`${inter.className} antialiased`}> <MSWComponent /> <AuthSession> {children} </AuthSession> </body> </html> ); } /src/app/_component'use client'; import { SessionProvider } from 'next-auth/react'; import { ReactNode } from 'react'; export default function AuthSession({children}: {children: ReactNode}) { return ( <SessionProvider>{children}</SessionProvider> ) } /src/app/api/auth/[...nextauth]/route.tsimport { handlers } from "@/auth" // Referring to the auth.ts we just created export const { GET, POST } = handlers; 폴더구조📦src ┣ 📂app ┃ ┣ 📂(afterLogin) ┃ ┃ ┣ 📂(home) ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┣ 📜mbtiCarousel.module.css ┃ ┃ ┃ ┃ ┣ 📜MbtiCarousel.tsx ┃ ┃ ┃ ┃ ┗ 📜UserCardList.tsx ┃ ┃ ┃ ┗ 📂_lib ┃ ┃ ┃ ┃ ┗ 📜getUserAll.ts ┃ ┃ ┣ 📂@modal ┃ ┃ ┃ ┣ 📂(.)promise ┃ ┃ ┃ ┃ ┗ 📂form ┃ ┃ ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┃ ┣ 📂[userId] ┃ ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┃ ┣ 📜UserDetailContent.tsx ┃ ┃ ┃ ┃ ┃ ┣ 📜UserDetailPromise.tsx ┃ ┃ ┃ ┃ ┃ ┣ 📜UserDetailTop.tsx ┃ ┃ ┃ ┃ ┃ ┣ 📜UserInfo.tsx ┃ ┃ ┃ ┃ ┃ ┗ 📜UsrCarousel.tsx ┃ ┃ ┃ ┃ ┣ 📂_lib ┃ ┃ ┃ ┃ ┃ ┣ 📜getAUser.ts ┃ ┃ ┃ ┃ ┃ ┗ 📜getUserPromise.ts ┃ ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┃ ┗ 📜default.tsx ┃ ┃ ┣ 📂like ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┣ 📜LikeCard.tsx ┃ ┃ ┃ ┃ ┣ 📜LikeTabProvider.tsx ┃ ┃ ┃ ┃ ┣ 📜Tab.tsx ┃ ┃ ┃ ┃ ┣ 📜TabDecider.tsx ┃ ┃ ┃ ┃ ┣ 📜UserILike.tsx ┃ ┃ ┃ ┃ ┗ 📜UserLikeMe.tsx ┃ ┃ ┃ ┣ 📂_lib ┃ ┃ ┃ ┃ ┣ 📜getUserILike.ts ┃ ┃ ┃ ┃ ┗ 📜getUserLikeMe.ts ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂messages ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂profile ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂promise ┃ ┃ ┃ ┣ 📂form ┃ ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┣ 📜PromiseCard.tsx ┃ ┃ ┃ ┃ ┣ 📜PromiseCardDropdown.tsx ┃ ┃ ┃ ┃ ┣ 📜PromiseCardLink.tsx ┃ ┃ ┃ ┃ ┣ 📜PromiseFormButton.tsx ┃ ┃ ┃ ┃ ┣ 📜promiseSection.module.css ┃ ┃ ┃ ┃ ┗ 📜PromiseSection.tsx ┃ ┃ ┃ ┣ 📂_lib ┃ ┃ ┃ ┃ ┗ 📜getPromiseAll.ts ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂recommend ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┗ 📜RecommendSection.tsx ┃ ┃ ┃ ┣ 📂_lib ┃ ┃ ┃ ┃ ┗ 📜getUserRecommends.ts ┃ ┃ ┃ ┣ 📜page.tsx ┃ ┃ ┃ ┗ 📜recommend.module.css ┃ ┃ ┣ 📂search ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┣ 📜SearchCard.tsx ┃ ┃ ┃ ┃ ┣ 📜SearchForm.tsx ┃ ┃ ┃ ┃ ┗ 📜SearchResult.tsx ┃ ┃ ┃ ┣ 📂_lib ┃ ┃ ┃ ┃ ┗ 📜getSearchResult.ts ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂setting ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂[userId] ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┣ 📜Back.tsx ┃ ┃ ┃ ┣ 📜ImageWithPlaceholder.tsx ┃ ┃ ┃ ┣ 📜LogoutButton.tsx ┃ ┃ ┃ ┣ 📜MainTitle.tsx ┃ ┃ ┃ ┣ 📜MbtiRecommendSection.tsx ┃ ┃ ┃ ┣ 📜Modal.tsx ┃ ┃ ┃ ┣ 📜RQProvider.tsx ┃ ┃ ┃ ┣ 📜SearchForm.tsx ┃ ┃ ┃ ┣ 📜userCard.module.css ┃ ┃ ┃ ┣ 📜UserCard.tsx ┃ ┃ ┃ ┣ 📜UserCardArticle.tsx ┃ ┃ ┃ ┗ 📜UserRandomRecommendSection.tsx ┃ ┃ ┣ 📂_lib ┃ ┃ ┃ ┣ 📜getBase64.ts ┃ ┃ ┃ ┗ 📜getUserRandomRecommends.ts ┃ ┃ ┣ 📜layout.module.css ┃ ┃ ┣ 📜layout.tsx ┃ ┃ ┗ 📜page.tsx ┃ ┣ 📂(beforeLogin) ┃ ┃ ┣ 📂login ┃ ┃ ┃ ┣ 📜login.module.css ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┃ ┣ 📂signup ┃ ┃ ┃ ┣ 📜page.tsx ┃ ┃ ┃ ┗ 📜signup.module.css ┃ ┃ ┣ 📂userSetting ┃ ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┃ ┣ 📜BirthdaySelect.tsx ┃ ┃ ┃ ┃ ┣ 📜DrinkSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜GenderSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜ImageSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜JobSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜MbtiSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜NicknameSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜RegionSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜ReligionSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜SchoolSelect.tsx ┃ ┃ ┃ ┃ ┣ 📜SetUser.tsx ┃ ┃ ┃ ┃ ┣ 📜SetUser2.tsx ┃ ┃ ┃ ┃ ┣ 📜SetUserComplete.tsx ┃ ┃ ┃ ┃ ┣ 📜SetUserProvider.tsx ┃ ┃ ┃ ┃ ┣ 📜SetUserProvider2.tsx ┃ ┃ ┃ ┃ ┣ 📜SetUserTop.tsx ┃ ┃ ┃ ┃ ┣ 📜SmokeSelect.tsx ┃ ┃ ┃ ┃ ┗ 📜TallSelect.tsx ┃ ┃ ┃ ┣ 📜page.tsx ┃ ┃ ┃ ┗ 📜userSetting.module.css ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┣ 📜title.module.css ┃ ┃ ┃ ┗ 📜Title.tsx ┃ ┃ ┗ 📂_lib ┃ ┃ ┃ ┗ 📜login.ts ┃ ┣ 📂api ┃ ┃ ┗ 📂auth ┃ ┃ ┃ ┗ 📂[...nextauth] ┃ ┃ ┃ ┃ ┗ 📜route.ts ┃ ┣ 📂_component ┃ ┃ ┣ 📜AuthSession.tsx ┃ ┃ ┣ 📜BottomNav.tsx ┃ ┃ ┣ 📜LeftNav.tsx ┃ ┃ ┣ 📜MSWComponent.tsx ┃ ┃ ┣ 📜nav.module.css ┃ ┃ ┗ 📜TopNav.tsx ┃ ┣ 📜favicon.ico ┃ ┣ 📜globals.css ┃ ┗ 📜layout.tsx ┣ 📂components ┃ ┗ 📂ui ┃ ┃ ┣ 📜avatar.tsx ┃ ┃ ┣ 📜badge.tsx ┃ ┃ ┣ 📜button.tsx ┃ ┃ ┣ 📜card.tsx ┃ ┃ ┣ 📜carousel.tsx ┃ ┃ ┣ 📜dropdown-menu.tsx ┃ ┃ ┣ 📜form.tsx ┃ ┃ ┣ 📜input.tsx ┃ ┃ ┣ 📜label.tsx ┃ ┃ ┣ 📜progress.tsx ┃ ┃ ┣ 📜skeleton.tsx ┃ ┃ ┣ 📜textarea.tsx ┃ ┃ ┗ 📜tooltip.tsx ┣ 📂lib ┃ ┗ 📜utils.ts ┣ 📂mocks ┃ ┣ 📜browser.ts ┃ ┣ 📜handlers.ts ┃ ┗ 📜http.ts ┣ 📂model ┃ ┣ 📜Post.ts ┃ ┣ 📜postImage.ts ┃ ┣ 📜User.ts ┃ ┗ 📜UserImage.ts ┣ 📜auth.ts ┗ 📜middleware.ts 로컬에서 잘되다가 어느순간부터 됐다 안됐다 하다가 이제는 안되고 있습니다. 어느 부분을 좀 더 찾아보고 해야할지 조언주시면 정말 감사하겠습니다.
-
해결됨Next + React Query로 SNS 서비스 만들기
prefetchQuery 적용 후 Warning: Text content did not match. 오류가 발생합니다.
안녕하세요. 강의 잘 보고 있습니다.!!👍👍react-query를 적용 중 오류가 표시되어 오류와 궁금한 부분이 있어서 문의 드립니다.Text content did not match. 오류가 발생하는데 어느 부분이 문제인지 잘 모르겠습니다 ㅠㅠprefetchQuery 를 사용하여 서버에서 post(트윗)데이터를 프리패치 후 TweetList컴포넌트에서 useQuery를 사용하게 만들었습니다. Post의 데이터는 msw에서 알려주신 faker를 통해서 요청마다 content를 동적으로 생성하게 했구요. 콘솔로 출력한 데이터와 reactQuery개발 도구의 데이터는 동일한데 화면에 표기된 데이터는 전혀 다른 데이터로 표시되네요..그리고 방식이 prefetchQuery 를 사용한 데이터는 staleTime과 상관없이 Fresh상태로 되어 useQuery 호출 시 데이터가 아직 fresh한 상태이므로 서버를 호출하지 않고 캐쉬에서 가져와 보여주는 방식이 맞나요?오류로그app-index.js:33 Warning: Text content did not match. Server: "Tener adulatio decens conitor. Thesis apostolus ago at decerno. Iste uberrime commodo. Verus amitto quas cometes delicate. Cognomen alii curto ciminatio. Solitudo complectus tristis. Teneo sum vindico. Adhuc decimus triumphus ipsa arguo umquam addo adulatio cresco. Sponte degenero non trado cauda beneficium laboriosam approbo." Client: "Tremo collum sint terror templum summisse viduo usque unus benevolentia. Eligendi substantia concido amissio uredo turpis aperte. Admoneo titulus audeo conicio fuga." at div at div at div at article at TweetWrapper (webpack-internal:///(app-pages-browser)/./src/app/(afterLogin)/home/_components/TweetWrapper.tsx:11:11) at Tweet (webpack-internal:///(app-pages-browser)/./src/app/(afterLogin)/home/_components/Tweet.tsx:31:11) at TweetList (webpack-internal:///(app-pages-browser)/./src/app/(afterLogin)/home/_components/TweetList.tsx:16:93) at HydrationBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/@tanstack+react-query@5.39.0_react@18.2.0/node_modules/@tanstack/react-query/build/modern/HydrationBoundary.js:14:11) at HomeContextProvider (webpack-internal:///(app-pages-browser)/./src/app/(afterLogin)/home/_components/Provider.tsx:17:11) at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:242:11) at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/redirect-boundary.js:74:9) at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/redirect-boundary.js:82:11) at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/not-found-boundary.js:84:11) at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:340:11) at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/error-boundary.js:162:11) at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:152:9) at ScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:227:11) at RenderFromTemplateContext (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/render-from-template-context.js:16:44) at OuterLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:359:11) at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:242:11) at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/redirect-boundary.js:74:9) at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/redirect-boundary.js:82:11) at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/not-found-boundary.js:84:11) at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:340:11) at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/error-boundary.js:162:11) at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/.pnpm/next@14.1.4_@babel+core@7.24.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/client/components/layout-router.js:152:9) at ScrollAndFocu소스코드(Tweet이 Post입니다! 나중에 바꿔야겠네여)[page.tsx] /homeimport React from "react"; import HomeTopTab from "./_components/HomeTopTab"; import WriteForm from "./_components/WriteForm"; import TweetList from "./_components/TweetList"; import HomeContextProvider from "./_components/Provider"; import { QueryClient, dehydrate, HydrationBoundary, } from "@tanstack/react-query"; import getPostRecommends from "./_lib/getPostRecommends"; const HomePage = async () => { const queryClient = new QueryClient(); await queryClient.prefetchQuery({ queryKey: ["tweet", "recommends"], queryFn: getPostRecommends, }); const dehydratedState = dehydrate(queryClient); return ( <HomeContextProvider> <HomeTopTab /> <WriteForm /> <HydrationBoundary state={dehydratedState}> <TweetList /> </HydrationBoundary> </HomeContextProvider> ); }; export default HomePage; TweetList.tsx"use client"; import React from "react"; import Tweet from "./Tweet"; import getPostRecommends from "../_lib/getPostRecommends"; import { Post } from "./TweetWrapper"; import { QueryClient, useQuery } from "@tanstack/react-query"; const TweetList = () => { const { data: tweets } = useQuery<Post[]>({ queryKey: ["tweet", "recommends"], queryFn: getPostRecommends, enabled: false, }); console.log("🚀 _ TweetList _ tweets:", tweets); return tweets?.map((tweet) => <Tweet post={tweet} key={tweet.postId} />); }; export default TweetList;
-
미해결Next + React Query로 SNS 서비스 만들기
찜하기 관련 질문드립니다.
안녕하세요 상세페이지에서 찜하기 요청을 하게되면 users/favorite/${peopleId}로 post 요청을 보내게되고 그럼 users/favorite api에 찜한 사람들의 목록이 추가됩니다.찜하기를 눌렀을경우 아이콘의 컬러를 변경시켜야해서 getQueryData로 찜한 사람들의 목록 을 가져오려고 하였는데 const { data: likePeopleList } = useQuery<GetPeoples>({ queryKey: ["get", "likepeoples"], queryFn: getLikePeoples, staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준 gcTime: 300 * 1000, });위에 코드가 없으면 likeQuery를 가져오지 못하고있는것같습니다. getQueryData로 가져오는 방법이 잘못된걸까요? 다른 좋은 방법있다면 여쭤보고싶습니다.밑에는 전체 코드입니다. type Props = { peopleId: string; }; export default function PeoplePosts({ peopleId }: Props) { const { data } = useQuery< GetPeoplePost, Object, GetPeoplePost, [_1: string, _2: string, _3: string] >({ queryKey: ["get", "peoplesDetail", peopleId], queryFn: getPeopleDetail, }); const { data: likePeopleList } = useQuery<GetPeoples>({ queryKey: ["get", "likepeoples"], queryFn: getLikePeoples, staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준 gcTime: 300 * 1000, }); const { content, nickname, userFileUrl, favoriteCount, viewCount, softSkill, techStack, links, position, alarmStatus, year, } = data?.data ?? {}; const queryClient = useQueryClient(); const likeQuery = queryClient.getQueryData<GetPeoples>([ "get", "likepeoples", ]); console.log("likeQuery", likeQuery); const liked = !!likeQuery?.data.find( (item) => item.userId === Number(peopleId), ); console.log("liked", liked); const like = useMutation({ mutationFn: (peopleId: string) => { return fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/users/favorite/${peopleId}`, { method: "post", }, ); }, onMutate(peopleId: string) { const oldData = queryClient.getQueryData<GetPeoples>([ "get", "likepeoples", ]); if (oldData) { const newData = { ...oldData, data: oldData.data.map((item) => ({ ...item, userId: Number(peopleId), })), }; queryClient.setQueryData(["get", "likepeoples"], newData); } }, }); const unLike = useMutation({ mutationFn: (peopleId: string) => { return fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/users/favorite/${peopleId}`, { method: "delete", }, ); }, onMutate(peopleId: string) { const oldData = queryClient.getQueryData<GetPeoples>([ "get", "likepeoples", ]); if (oldData) { const deleteData = { ...oldData, data: oldData.data.filter((item) => item.userId !== Number(peopleId)), }; queryClient.setQueryData(["get", "likepeoples"], deleteData); } }, }); const onLike: MouseEventHandler<HTMLButtonElement> = (e) => { e.preventDefault(); if (liked) { unLike.mutate(peopleId); } else { like.mutate(peopleId); } }; return ( <div className="flex flex-col"> <div className="flex flex-col gap-4 border-b pb-10"> <div className="flex items-center gap-[10px]"> <Image src={`${userFileUrl}`} alt="유저프로필" width={30} height={30} /> <h1 className="text-[32px] font-bold">{nickname}</h1> <div> <BlueTextBox textSize="12px" textToShow={`${position}`} /> </div> </div> <div className="flex flex-col gap-2"> {softSkill ?.split(",") .map((skill, i) => <HashTag text={skill} key={i} />)} </div> <div className="flex gap-3"> <HeartEyeIconBox count={favoriteCount as number} icon={heartIcon} /> <HeartEyeIconBox count={viewCount as number} icon={eyeIcon} /> </div> </div> <div className="mt-[42px] flex flex-col gap-[50px]"> <div className="people-post-grid"> <h1 className="text-[22px] font-bold">경력</h1> <h3>{year}</h3> </div> <div className="people-post-grid"> <h1 className="text-[22px] font-bold">사용언어</h1> <div className="flex gap-2"> {techStack ?.split(",") .map((stack, i) => ( <TechStack techStack={stack} showText key={`stack${i}`} /> ))} </div> </div> <div className="flex flex-col gap-3"> <h1 className="text-[22px] font-bold">자기소개</h1> <p>{content}</p> </div> <div className="flex flex-col gap-3"> <h1 className="text-[22px] font-bold">Link</h1> <Link href={links as string}>{links}</Link> </div> </div> <div className="mt-[60px] flex gap-[13px] self-center"> <button className={`h-[58px] w-[142px] rounded-md bg-neutral-orange-500 font-bold ${alarmStatus ? "text-neutral-white-0" : "text-neutral-black-800"}`} > {alarmStatus ? "제안하기" : "제안불가"} </button> <button onClick={onLike} className="flex h-[58px] w-[58px] flex-col items-center justify-center rounded-md border" > {liked ? ( <Image src={fillHeartIcon} alt="하트아이콘" width={20} height={20} /> ) : ( <Image src={heartIcon} alt="하트아이콘" width={20} height={20} /> )} <h5 className="text-[12px]">{favoriteCount}</h5> </button> </div> </div> ); }
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
geolocation부분에 대해 질문있습니다.
geolocation부분에const askForLocation = function () { navigator.geolocation.getCurrentPosition((position) => { console.log(position); }); }; askForLocation();이렇게 함수가 있는데 여기서 궁금한점이 askForLocation(); 함수 호출부분에 인자로 전달하는 것이 없는데 매개변수로 position에 위치정보 객체형식으로 콘솔에 나오는 이유가 뭔지 궁금합니다.
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
3000번은 잘 들어가지는데 80번은 안됩니다.
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000까지 하고 3000번 포트로 잘 들어가지는데 3000번포트를 지우고 들어가봐도 뒤에 :80을 붙여 넣어 들어가봐도 사이트에 연결할 수 없음이 뜨네요 왜 그럴까요??
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
함수, 변수의 호이스팅 부분 질문있습니다.
함수, 변수의 호이스팅 강의 영상 부분에if (storageData?.complete) { newLi.classList.add("complete"); }이 코드에서 storageData 뒤에 ? 이 물으표가 없으면 매개변수를 받아오지 않게 되니 undefined라고 강사님이 말씀하시는데 이게 무슨 말인지 잘 모르겠습니다. 그리고 ToDoList에서 리스트에 추가를 하고 더블클릭 삭제, 전체 삭제까지는 어느정도 이해가 되는데 로컬스트리지 전체 부분이 조금 이해도 어려운데 어떻게 이해를 하면서 공부를 하면 좋을까요?
-
해결됨Next + React Query로 SNS 서비스 만들기
spring boot를 사용한 social login
Next.js와 Spring boot를 사용해서 소셜 로그인을 추가하려고 합니다.소셜 로그인의 경우 코드와 토큰을 프론트에서 관리하지 않는 것이 좋다고 하여 백엔드에서 모든 로직을 처리하고 있습니다. 현재 프론트에서 window.location.href = "http://localhost:8080/oauth2/authorization/google";위와 같은 경로로 백엔드로 소셜 로그인 요청을 보내고 백엔드에서는 소셜 로그인을 진행한 뒤에 유저 정보를 생성하고 JWT를 생성한 뒤 응답의 헤더에 쿠키 형태로 JWT를 넣어 response.sendRedirect("http://localhost:3000/auth/social");로 리다이렉트하고 있습니다. 프론트에서는 /auth/social 페이지에서 쿠키에 있는 JWT를 꺼내 유저 정보를 가져오는 API를 다시 호출해 유저 정보를 가져오고 있습니다.이 후 auth.js 라이브러리를 통한 session 관리를 하고자 하는데 session을 업데이트 하려면 어떻게 해야 하나요..?(session.user가 있는지 없는지를 통한 로그인 체크를 위해 사용한다고 이해했습니다.) 서버 컴포넌트에서 import { auth } from "@/auth"; 를 통해 가져온 session에 데이터를 넣어보았지만 데이터가 제대로 들어가지 않는 것 같아 조언을 구해봅니다..
-
미해결[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
객체 localStorage 부분 질문있습니다.
현재 객체 localStorage저장 부분의 인강을 보다 궁금한점 있어 질문을 드립니다.const saveItemsFn = function () { const saveItems = []; for (let i = 0; i < todoList.children.length; i++) { const todoObj = { contents: todoList.children[i].querySelector("span").textContent, complete: todoList.children[i].classList.contains("complete"), }; saveItems.push(todoObj); } localStorage.setItem("saved-items", JSON.stringify(saveItems)); };현재 자바스크립트 코드 제일 마지막 부분에 saveItemsFn함수가 저장하는 부분이니 이 함수안에 localStorage.setItem을 사용해서 로컬스토리지에 저장을 하는것까지는 이해가 되었는데 저장된걸 가져오기 위해 const savedTodoList = localStorage.getItem("saved-items");localStorage.getItem을 사용하는데 여기서 첫번째로 이 코드 위치가 다시 제일 위쪽에 작성이 되었는지 궁금하고 두번째로 이 코드가 saveItemsFn 함수 안에 작성이 되지 않은 이유는 getItem이 저장하는 코드가 아니기때문에 saveItemsFn안이 아닌 따로 다시 작성이 된것인가요?
-
해결됨Next + React Query로 SNS 서비스 만들기
로그인 관련 질문입니다.
https://www.inflearn.com/questions/1268586/%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%97%90%EB%9F%AC-%EC%A7%88%EB%AC%B8%EC%9E%85%EB%8B%88%EB%8B%A4여기에서 질문했던 로그인 관련 문제입니다.지금 현재 로그인 후 로그아웃 후 다른 아이디로 재로그인시에 로그아웃 버튼에 session정보가 제대로 안들어가는 것 같습니다.처음 로그인 했을 때 로그아웃에 session 정보가 들어가고, 로그아웃 후 다른 아이디로 재로그인시에 로그아웃버튼에 로그아웃전의 계정의 정보가 들어가 있습니다. 백엔드 서버 콘솔에는 정보가 제대로 들어가 있지만, let session = await auth(); 에서 session정보가 제대로 안 받아지는건지, 아니면 캐싱된 정보가 계속 쓰이는 건지 모르겠지만, 정보가 제대로 안들어갑니다.물론 새로고침시에 정상적으로 정보가 들어가집니다.제 프로젝트에서 문제가 있는건가 싶어서, 코드를 비교해보고 next, next-auth 버전을 바꿔보기도 했지만, 해결이 안되어서, 배포된 https://z.nodebird.com/ 링크로도 해보았는데 똑같은 버그가 있는 것 같아서 질문드립니다.무엇이 문제인지 궁금합니다. 좋은 하루 보내세요!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
graphql codegen 설치
섹션 10에서 graphql codegen 설치하려는데요강의에서는 yarn add -D @graphql-codegen/cli을 설치하라고 하는데 지금 설치하려고 사이트에 들어가니yarn add --dev typescript @graphql-codegen/cli로 되어 있는데 같은 건가요?그냥 아래 명령어 실행해도 되나요?
-
미해결Next + React Query로 SNS 서비스 만들기
client side에서 useSession 값이 undefined
선생님 안녕하세요 사이드플젝하면서다시 보고있는데, 클라이언트 사이드에서 useSession데이터가 없어서 질문 드립니다. import NextAuth from "next-auth" import Credentials from "next-auth/providers/credentials" export const { handlers, signIn, signOut, auth } = NextAuth({ pages: { signIn: '/login', newUser: '/signup', }, providers: [ Credentials({ // You can specify which fields should be submitted, by adding keys to the `credentials` object. // e.g. domain, username, password, 2FA token, etc. credentials: { id: {}, password: {}, }, authorize: async (credentials) => { console.log(credentials, '-------------------credentials'); const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(credentials), }) console.log(authResponse.ok, '-----------------------------authResponse.ok'); if (!authResponse.ok) { return null; } let user = await authResponse.json(); // return user object with the their profile data console.log(user, '--------------------------------'); return { id: user.id, email: user.id, name: user.nickname, image: user.image, ...user, } }, }), ], })먼저 auth.ts에서 유저 정보를 잘 받아와서 return해주는 것 확인하고,/profile/page.ts (서버클라이언트)/profile/_component/logoutButton (클라이언트 컴퍼넌트)에서 각각 세션을 확인해 봤습니다. (서버 컴포넌트)import { auth } from '@/auth'; const session = await auth(); console.log(session, '------------server side session'); if (!session?.user) { redirect('/login'); }(클라리언트 컴포넌트)'use client'; import { Button } from '@/components/ui/button'; import { useCallback } from 'react'; // client component에서만! import { signOut, useSession } from 'next-auth/react'; import { useRouter } from 'next/navigation'; export default function LogoutButton() { const router = useRouter(); const { data: me } = useSession(); const onLogout = useCallback(() => { signOut({redirect: false}).then(() => {router.replace('/')}); }, [router]); console.log(me, '------------client side session'); if (!me?.user) return null; return ( <Button className='w-full' onClick={onLogout}>로그아웃</Button> ) }결과로와같이 클라리언트 사이드에서는 데이터가 없더라구요.혹시 어떤부분을 좀 더 봐야할지 알 수 있을까요?그리고 useSession을 호출하면서Failed to load resource: the server responded with a status of 404 (Not Found)app-index.js:33 ClientFetchError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON at fetchData (client.js:49:22) at async getSession (react.js:109:21) at async __NEXTAUTH._getSession (react.js:270:43)session 404가 계속나오는데 제가 잘못 호출하고있는건지 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
link태그를 사용하는데 페이지가 새로고침이 됩니다.
안녕하세요 선생님강의보면서 플젝을 만들다가 여쭤보고 싶은게 생겼습니다.📦(afterLogin) ┣ 📂(home) ┃ ┗ 📂_component ┃ ┃ ┣ 📜mbtiCarousel.module.css ┃ ┃ ┗ 📜MbtiCarousel.tsx ┣ 📂@modal ┃ ┣ 📂(.)promise ┃ ┃ ┗ 📂form ┃ ┃ ┃ ┗ 📜page.tsx ┃ ┣ 📂[userId] ┃ ┃ ┣ 📂_component ┃ ┃ ┃ ┗ 📜UsrCarousel.tsx ┃ ┃ ┗ 📜page.tsx ┃ ┗ 📜default.tsx ┣ 📂like ┃ ┗ 📜page.tsx ┣ 📂messages ┃ ┗ 📜page.tsx ┣ 📂profile ┃ ┗ 📜page.tsx ┣ 📂promise ┃ ┣ 📂form ┃ ┃ ┗ 📜page.tsx ┃ ┣ 📂_component ┃ ┃ ┣ 📜PromiseFormButton.tsx ┃ ┃ ┣ 📜promiseSection.module.css ┃ ┃ ┗ 📜PromiseSection.tsx ┃ ┗ 📜page.tsx ┣ 📂recommend ┃ ┣ 📂_component ┃ ┃ ┗ 📜RecommendSection.tsx ┃ ┣ 📜page.tsx ┃ ┗ 📜recommend.module.css ┣ 📂setting ┃ ┗ 📜page.tsx ┣ 📂[userId] ┃ ┗ 📜page.tsx ┣ 📂_component ┃ ┣ 📜Back.tsx ┃ ┣ 📜FriendRecommendSection.tsx ┃ ┣ 📜MainTitle.tsx ┃ ┣ 📜MbtiRecommendSection.tsx ┃ ┣ 📜Modal.tsx ┃ ┣ 📜userCard.module.css ┃ ┣ 📜UserCard.tsx ┃ ┗ 📜UserCardArticle.tsx ┣ 📜layout.module.css ┣ 📜layout.tsx ┗ 📜page.tsx이런구조에서(afterLogin) > UserCard 를 클릭하면@modal > [userId] > page.tsx가 모달창으로 뜨게 됩니다.새로고침해도 모달창이 뜨게 되어있습니다. 이게 로컬에서는 잘 작동하는데테스트하려고 vercel에 배포해서 확인했더니 url은 바뀌는데 새로고침이 되고 화면은 바뀌지 않더라구요.구글링해도 만족스런 답변이 없어서 이렇게 글을 남깁니다.return ( // <UserCardArticle user={user}> <Card className={style.userCard}> <Link href={`/${user.id}`} scroll={false} className='w-full h-full absolute top-0 left-0'> <img src={user.image[0]} className='rounded-xl h-full block w-full' alt="img" /> <div className={style.userInfo}> <h2 className='text-white font-extrabold text-xl'>{user.mbti.mbti}, 궁합 {user.mbti.score}%</h2> <h2 className='text-white font-extrabold text-xl'>{user.nickname}, {user.age}</h2> <p className='text-white font-semibold text-base'>{user.distance}km, {user.area}</p> </div> </Link> <div className='absolute bottom-3 px-3 w-full'> <Button variant={'default'} className='bg-white hover:bg-slate-50 w-full'> <UserPlus color='#000000' /> <span className='ml-2 text-black font-extrabold'>친구신청</span> </Button> </div> </Card> // </UserCardArticle> )기존 선생님처럼 UserCardArticle이란 컴포넌트를 만들어서 router.push도 해봤다가 link태그로 고쳐봤는데도 새로고침이 되어서 어떤부분을 봐야할지 조언 듣고 싶습니다.감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션4 01-02-emotion 에러가 나는데 못찾겠습니다ㅜ
설치가 잘못된 걸까요.. yarn dev하니 오류가 납니다ㅜ
-
미해결Next + React Query로 SNS 서비스 만들기
로그인후 replace가 안되는 이유?
지금 로그인 후 핸들러에서 값을 잘 주는것을 확인했고auth.ts의콘솔 부분에 값이 잘 나오는것을 확인했습니다여기서 result에서도 성공했다고 나오는데 replace가 안되네요이유가 뭘까요