묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨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;
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
로그아웃할때 /server/uploads/index.html' 파일을 찾을수없다고 에러가 나오는데 어떻게해야할까요?
로그아웃 버튼을 클릭하면 Error: ENOENT: no such file or directory, stat '/Users/user/Documents/code/MatzipApp/server/uploads/index.html'이런 에러가 나오고있어서 uploads폴더에 Index.html파일을 추가하니까 에러는 안나오는데 index.html에 아무것도 안작성해도되나요?
-
미해결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> ); }
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
"실행 오류" yarn start 실행후
r - reload the appd - open developer menui - run on iOSa - run on Androidinfo Opening the app on Android...info JS server already running.info Launching emulator...info Installing the app...> Task :gradle-plugin:compileKotlin UP-TO-DATE> Task :gradle-plugin:compileJava NO-SOURCE> Task :gradle-plugin:pluginDescriptors UP-TO-DATE> Task :gradle-plugin:processResources UP-TO-DATE> Task :gradle-plugin:classes UP-TO-DATE> Task :gradle-plugin:jar UP-TO-DATE> Task :gradle-plugin:inspectClassesForKotlinIC UP-TO-DATE> Task :app:buildCodegenCLI SKIPPED> Task :app:generateCodegenSchemaFromJavaScript SKIPPED> Task :app:generateCodegenArtifactsFromSchema SKIPPED> Task :app:generatePackageList> Task :app:preBuild> Task :app:preDebugBuild> Task :app:compileDebugAidl NO-SOURCE> Task :app:compileDebugRenderscript NO-SOURCE> Task :app:generateDebugBuildConfig UP-TO-DATE> Task :app:javaPreCompileDebug UP-TO-DATE> Task :app:checkDebugAarMetadata UP-TO-DATE> Task :app:generateDebugResValues UP-TO-DATE> Task :app:mapDebugSourceSetPaths UP-TO-DATE> Task :app:generateDebugResources UP-TO-DATE> Task :app:mergeDebugResources UP-TO-DATE> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE> Task :app:extractDeepLinksDebug UP-TO-DATE> Task :app:processDebugMainManifest UP-TO-DATE> Task :app:processDebugManifest UP-TO-DATE> Task :app:processDebugManifestForPackage UP-TO-DATE> Task :app:processDebugResources UP-TO-DATE> Task :app:compileDebugJavaWithJavac UP-TO-DATE> Task :app:mergeDebugShaders UP-TO-DATE> Task :app:compileDebugShaders NO-SOURCE> Task :app:generateDebugAssets UP-TO-DATE> Task :app:mergeDebugAssets UP-TO-DATE> Task :app:compressDebugAssets UP-TO-DATE> Task :app:processDebugJavaRes NO-SOURCE> Task :app:mergeDebugJavaResource UP-TO-DATE> Task :app:checkDebugDuplicateClasses UP-TO-DATE> Task :app:desugarDebugFileDependencies UP-TO-DATE> Task :app:mergeExtDexDebug UP-TO-DATE> Task :app:mergeLibDexDebug UP-TO-DATE> Task :app:dexBuilderDebug UP-TO-DATE> Task :app:mergeProjectDexDebug UP-TO-DATE> Task :app:mergeDebugJniLibFolders UP-TO-DATE> Task :app:mergeDebugNativeLibs UP-TO-DATE> Task :app:stripDebugDebugSymbols UP-TO-DATE> Task :app:validateSigningDebug UP-TO-DATE> Task :app:writeDebugAppMetadata UP-TO-DATE> Task :app:writeDebugSigningConfigVersions UP-TO-DATE> Task :app:packageDebug UP-TO-DATE> Task :app:createDebugApkListingFileRedirect UP-TO-DATE> Task :app:installDebug FAILED38 actionable tasks: 2 executed, 36 up-to-dateinfo 💡 Tip: Make sure that you have set up your development environment correctly, by running react-native doctor. To read more about doctor command visit: https://github.com/react-native-community/cli/blob/main/packages/cli-doctor/README.md#doctorFAILURE: Build failed with an exception.* What went wrong:Execution failed for task ':app:installDebug'.> com.android.builder.testing.api.DeviceException: No connected devices!* Try:> Run with --stacktrace option to get the stack trace.> Run with --info or --debug option to get more log output.> Run with --scan to get full insights.* Get more help at https://help.gradle.orgBUILD FAILED in 5sinfo Run CLI with --verbose flag for more details.|후 실행이 안됩니다..어떻게 해야되나요?
-
해결됨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에 데이터를 넣어보았지만 데이터가 제대로 들어가지 않는 것 같아 조언을 구해봅니다..
-
해결됨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/ 링크로도 해보았는데 똑같은 버그가 있는 것 같아서 질문드립니다.무엇이 문제인지 궁금합니다. 좋은 하루 보내세요!
-
미해결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태그로 고쳐봤는데도 새로고침이 되어서 어떤부분을 봐야할지 조언 듣고 싶습니다.감사합니다.
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
[4-0] GoogleMap 연동하기 진행 중 구글맵에 오류가 발생 했습니다.
안녕하세요 강사님. 강의 잘 듣고 있습니다. :)강의 진행 중 구글맵을 띄우는 과정에서 ERROR react-native-maps: AirGoogleMaps dir must be added to your xCode project to support GoogleMaps on iOS. 라는 오류가 발생하는데요, 이 때문에 구글맵이 보이지 않아서 진행이 어려운 상태 입니다. 앞서 해당 강의에서 8분 가량 설명 해주신 부분은 모두 진행 하였는데요, 어떻게 하면 구글 맵을 띄울 수 있을까요?ㅜㅜ
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
로그인 api 요청 이후 getAccessToken ( /auth/refresh ) api 401 error
안녕하세여 강사님 강의 잘 듣고 있습니다.다름이 아니라 회원가입 및 로그인 api 요청 성공시 onSuccess 함수 로직에 있는queryClient.refetchQueries({ queryKey: [queryKeys.AUTH, queryKeys.GET_ACCESS_TOKEN], });이 코드로 getAccessToken ( /auth/refresh ) api 를 요청하고 있습니다. 여기서 문제는 getAccessToken 요청시 401 error 가 발생하고 있습니다. DB 에 회원가입으로 생성된 유저 데이터는 잘 생성된 상태이고 오타는 없어보입니다. ㅠㅠ 도와주세여 아래 이미지는 log 이미지입니다.
-
미해결Next + React Query로 SNS 서비스 만들기
로그인후 replace가 안되는 이유?
지금 로그인 후 핸들러에서 값을 잘 주는것을 확인했고auth.ts의콘솔 부분에 값이 잘 나오는것을 확인했습니다여기서 result에서도 성공했다고 나오는데 replace가 안되네요이유가 뭘까요
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
colors[theme]을 못읽는 이유
import React, {ReactNode} from 'react'; import { Pressable, StyleSheet, Text, PressableProps, Dimensions, View, StyleProp, ViewStyle, TextStyle, } from 'react-native'; import {colors} from '../../constants'; import useThemeStore from '@/store/useThemeStore'; import {ThemeMode} from '@/types/common'; interface CustomButtonProps extends PressableProps { label: string; variant?: 'filled' | 'outlined'; size?: 'large' | 'medium'; inValid?: boolean; style?: StyleProp<ViewStyle>; textStyle?: StyleProp<TextStyle>; icon?: ReactNode; } const deviceHeight = Dimensions.get('screen').height; function CustomButton({ label, variant = 'filled', size = 'large', inValid = false, style = null, textStyle = null, icon = null, ...props }: CustomButtonProps) { const {theme} = useThemeStore(); const styles = styling(theme); // 여기서는 제대로 출력이 됩니다. 값이 제대로 읽힙니다. console.log(colors[theme].PINK_700); return ( <Pressable disabled={inValid} style={({pressed}) => [ styles.container, pressed ? styles[`${variant}Pressed`] : styles[variant], inValid && styles.inValid, style, ]} {...props}> <View style={styles[size]}> {icon} <Text style={[styles.text, styles[`${variant}Text`], textStyle]}> {label} </Text> </View> </Pressable> ); } const styling = (theme: ThemeMode) => StyleSheet.create({ container: { borderRadius: 3, justifyContent: 'center', flexDirection: 'row', }, inValid: { opacity: 0.5, }, filled: { backgroundColor: colors[theme].PINK_700, }, outlined: { borderColor: colors[theme].PINK_700, borderWidth: 1, }, filledPressed: { backgroundColor: colors[theme].PINK_500, }, outlinedPressed: { borderColor: colors[theme].PINK_700, borderWidth: 1, opacity: 0.5, }, large: { width: '100%', paddingVertical: deviceHeight > 700 ? 15 : 10, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', gap: 5, }, medium: { width: '50%', paddingVertical: deviceHeight > 700 ? 12 : 8, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', gap: 5, }, text: { fontSize: 16, fontWeight: '700', }, filledText: { color: colors[theme].WHITE, }, outlinedText: { color: colors[theme].PINK_700, }, }); export default CustomButton; console.log(colors[theme].PINK_700); 이렇게 출력할 경우, 제대로 아래와 같이 출력이 됩니다만 스타일은 제대로 읽어오지 않습니다. 이 부분에 대해서 알고 싶습니다. BUNDLE ./index.js LOG Running "MatzipApp" with {"rootTag":171,"initialProps":{"concurrentRoot":false}} LOG light LOG #C63B64 LOG #C63B64 LOG #C63B64 ERROR TypeError: Cannot read property 'PINK_700' of undefined This error is located at: in CustomButton (created by ErrorBoundary) in RCTView (created by View) in View (created by ErrorBoundary) in ErrorBoundary (created by RetryErrorBoundary) in RetryErrorBoundary (created by RootNavigator) in RootNavigator (created by App) in EnsureSingleNavigator in BaseNavigationContainer in ThemeProvider in NavigationContainerInner (created by App) in _QueryClientProvider (created by App) in App in RCTView (created by View) in View (created by AppContainer) in RCTView (created by View) in View (created by AppContainer) in AppContainer in MatzipApp(RootComponent), js engine: hermes ERROR TypeError: Cannot read property 'WHITE' of undefined This error is located at: in RetryErrorBoundary (created by RootNavigator) in RootNavigator (created by App) in EnsureSingleNavigator in BaseNavigationContainer in ThemeProvider in NavigationContainerInner (created by App) in _QueryClientProvider (created by App) in App in RCTView (created by View) in View (created by AppContainer) in RCTView (created by View) in View (created by AppContainer) in AppContainer in MatzipApp(RootComponent), js engine: hermes ERROR TypeError: Cannot read property 'WHITE' of undefined This error is located at: in RetryErrorBoundary (created by RootNavigator) in RootNavigator (created by App) in EnsureSingleNavigator in BaseNavigationContainer in ThemeProvider in NavigationContainerInner (created by App) in _QueryClientProvider (created by App) in App in RCTView (created by View) in View (created by AppContainer) in RCTView (created by View) in View (created by AppContainer) in AppContainer in MatzipApp(RootComponent), js engine: hermes ERROR TypeError: Cannot read property 'WHITE' of undefined https://github.com/dydals3440/MatZip좀더 정확히 판단을 위하여 제가 커밋한 레포 남겨드립니다!!!
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
AWS S3 : 버킷에 사진이 업로드가 안됩니다(2)
[Nest] 27666 - 2024. 05. 23. 오후 12:23:25 ERROR [ExceptionsHandler] ENOENT: no such file or directory, stat '/Users/제이름/MatzipApp/server/uploads/index.html'Error: ENOENT: no such file or directory, stat '/Users/제이름/MatzipApp/server/uploads/index.html' 아까 올린 문제는 제가 지역을 잘못봐서 .env 파일에서 수정해서 해결했습니다. 다시 실행해보니 이번엔 저런 오류가 뜨는데욥실제로 저런 디렉토리랑 파일이 서버 하위에 없긴 합니다.. 구글링해도 도저히 답이 안나와서 다시 한번 질문 드립니다!
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
S3 실행시 버킷에 사진이 업로드가 안됩니다
기존에 있는 문제는 해결됐습니다!(개인정보가 있어서 삭제합니다ㅜㅜ)
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
회원가입 오류입니다!
일단 회원가입시 400 에러가 발생 합니다 ! 리퀘스트 인터셉터 에러 내용 {"adapter": ["xhr", "http", "fetch"], "baseURL": "http://localhost:3030", "data": {"email": "ajrfysd@naver.com", "password": "gsas22sgda"}, "env": {"Blob": [Function Blob], "FormData": [Function FormData]}, "headers": {"Accept": "application/json, text/plain, */*"}, "maxBodyLength": -1, "maxContentLength": -1, "method": "post", "timeout": 0, "transformRequest": [[Function transformRequest]], "transformResponse": [[Function transformResponse]], "transitional": {"clarifyTimeoutError": false, "forcedJSONParsing": true, "silentJSONParsing": true}, "url": "/auth/signup", "validateStatus": [Function validateStatus], "withCredentials": true, "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN"}리스폰스 인터셉터 [AxiosError: Request failed with status code 400]email, password로그도 잘 찍히고 하는데 왜 400이발생하는지 모르겠습니다..ㅠㅠ 서버쪽 같기도 한데 잘 모르겠네요..postgresql에 테이블도 잘 생성 되어 있고 npm run start:devApplication] Nest application successfully started +2ms http://localhost:3030 크롬에서 3030 으로 요청시 로그에 내줄 index.html없다고 하는거 보니 작동 하는것 같긴 한데...이상하게 Postman 에서는 couldnot send 나오고.../auth/signup도 마찬가지고... 다른 부분은 confirmPassword를 제가 rePassword로바꾸었는데 보내는 쪽에서도 비밀번호확인은 안보내는것 같고 받는 쪽에서도 아예 안받는것 같은데..혹시 위 내용으로 추측 가능한 부분이 있을까요??
-
미해결Next + React Query로 SNS 서비스 만들기
2:56 src/app/page.tsx 파일을 이동 후 not-found 페이지만 뜹니다.
다른분 질문도보고 답변도보고 수정도해보았는데 도저히 안됩니다... 폴더구조입니다. import 오류로 동영상 내용과 동일하게 ../ 를 추가 후 재 호출하면 아래와같이 나옵니다. 소스상 문제는없는것같은데.. 무엇이문제일까요..다른분질문에 AI가 라우팅문제일수있다 했는데 NEXT.CONFIG.JS에 따로 설정도없습니다.다른분질문보니 /app/(beforeLogin)/page.tsx를 넣은것은 /app/page.tsx와 같은거라고 답변이 달린것도봣는데 위 오류에서 벗어날수가없습니다..
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
로그인/회원가입 오류 질문 드립니다.
const postLogin = async ({ email, password, }: RequestUser): Promise<ResponseToken> => { console.log('postLogin'); const {data} = await axiosInstance.post('/auth/signin', {email, password}); console.log('data', data); return data; };회원가입에서 오류가 발생해서 db를 봤는데 db에 데이터는 들어가 있습니다. 그래서 로그인을 진행해 봤는데 로그인이 되질 않아 postLogin에 console을 찍어 보았더니 axios post 에서 아무런 값도 받아오질 못하고 있었습니다. 오류 코드는 뜨지 않구요. 시뮬레이터를 껏다 켜보기도 하고 서버를 껏다 켜보기도 했는데 이제는 회원가입 시 db에 저장도 되질 않습니다.환경은 윈도우/안드로이드 입니다.https://github.com/ghgfhfg2/react-native-base
-
미해결Next + React Query로 SNS 서비스 만들기
default.tsx를 넣는대신 modal의 타입을 ?로 하면안되나요?
modal이 없는 상황의 오류를 해결하기위해 제로초님이 default.tsx라는 파일을 소개해줬는데요, 그냥 layout.tsx에서 애초에 Probs를 정의할때 type Probs= modal?:reactNode로 하면 안될까요?
-
미해결Next + React Query로 SNS 서비스 만들기
msw patch
안녕하세요 msw patch 관련해서 여쭤보고싶은게 있습니다!제로초님 강의를 응용해서 프로젝트에 msw로 데이터들을 테스트 하고있습니다 handler에서 /users란 엔드포인트로 get요청후 데이터들을 받아온뒤 다시 수정이 필요해 patch handler를 생성했습니다. mutation을 통해서 patch 요청은 성공한거같은데 기존의 get으로 받아온 user데이터들을 수정하고 싶다면 어떻게 할수있을지 여쭤보고싶습니다 ! const mutation = useMutation({ mutationFn: async (e: FormEvent) => { e.preventDefault(); const updatedUser = { userId: product.userId, nickName: product.nickName, userFileUrl: product.userFileUrl, techStack: product.techStack, position: product.position, employmentStatus: product.employmentStatus, year: product.year, links: product.links, alarmStatus: product.alarmStatus, content: product.content, softSkill: product.softSkill, }; fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/users`, { method: "PATCH", body: JSON.stringify(updatedUser), }); }, }); import { bypass, http, HttpResponse } from "msw"; import { hotPeople, peoples, users } from "./peopleData"; export const handlers = [ http.get("/peoples/hot/:tag", () => { return HttpResponse.json(hotPeople); }), http.get("/peoples", ({ request, params }) => { return HttpResponse.json(peoples); }), http.get("/users", () => { return HttpResponse.json(users); }), http.patch("/users", async ({ request }) => { return HttpResponse.text("success?"); }), ]; export default handlers;
-
해결됨Next + React Query로 SNS 서비스 만들기
데이터 리페칭 질문이 있습니다.
안녕하세요 제로초님 강의를 듣던 중 궁금한 것이 있어서 여쭈어 봅니다. 강의에서는 데이터를 mutation으로 리페칭 후 if (queryClient.getQueryData(["posts", "recommends"])) { queryClient.setQueryData( ["posts", "recommends"], (prevData: { pages: Post[][] }) => { const shallow = { ...prevData, pages: [...prevData.pages], }; shallow.pages[0] = [...shallow.pages[0]]; shallow.pages[0].unshift(newPost); return shallow; } ); }이런 식으로 데이터를 업데이트 해주었는데, 이 부분을 아래와 같이 queryClient.invalidateQueries({ queryKey: ["posts", "recommends"] });이런 식으로 업데이트를 하면 어떤 차이점이 있나요 ??데이터 업데이트시 쿼리를 업데이트 하고 리페칭하는 동작은 같은 것 같은데, 강의에서와 같이 복잡한 데이터 구조를 복사 해가며 구현하는 이유가 궁금합니다.성능상의 차이가 있는 것인가요 ??