안녕하세요. 강사님 예제를 보고 하던 중 suspense 가 동작하지 않아 질문드립니다. 처음 예시로 알려주신 react-query의 isPending 을 사용한 로딩처리는 잘 동작하지만 마지막에 알려주신 useSuspense( useSuspenseInfiniteQuery, useSuspenseQuery )들을 사용하는 경우 동작하지 않네요.. * 팔로우 중 을 선택해도 suspense에 설정한 로딩 컴포넌트가 나오지 않고 딜레이된 시간(5초) 후 데이터가 보여집니다. 로딩 컴포넌트도 회전하지 않고 멈춰있습니다. 어떤부분을 봐야할까요?ㅠㅠ 반대로 이런 증상을 경험하니 이전 데이터가 먼저 보여진 후 5초 뒤에 최신 데이터로 보여지므로 사용자가 잘 못된 데이터를 표시 할 수 있다는걸 배울 수 있었습니다. 😎 소스코드 const HomePage = async () => { return ( <HomeContextProvider> <HomeTopTab /> <WriteForm /> <Suspense fallback={<Loader />}> <TabDividerSuspense /> </Suspense> </HomeContextProvider> ); }; const TabDividerSuspense = async () => { const queryClient = new QueryClient(); await queryClient.prefetchInfiniteQuery({ queryKey: ["tweet", "recommends"], queryFn: getPostRecommends, initialPageParam: 0, }); const dehydratedState = dehydrate(queryClient); return ( <HydrationBoundary state={dehydratedState}> <TabDivider /> </HydrationBoundary> ); }; const TabDivider = () => { const { tab } = useContext(HomeContext); return tab === "recommended" ? <TweetList /> : <FollowingList />; }; const TweetList = () => { const { ref, inView } = useInView(); const { data, fetchNextPage, hasNextPage, isFetching, isPending } = useSuspenseInfiniteQuery< Post[], object, InfiniteData<Post[]>, [string, string], number >({ queryKey: ["tweet", "recommends"], queryFn: getPostRecommends, initialPageParam: 0, getNextPageParam: (lastPage) => lastPage.at(-1)?.postId, }); useEffect(() => { if (inView) { !isFetching && hasNextPage && fetchNextPage(); } }, [fetchNextPage, hasNextPage, inView, isFetching]); const tweets = useMemo(() => { if (data) { return data.pages.flat(); } }, [data]); return ( <> {tweets?.map((tweet) => ( <Tweet post={tweet} key={tweet.postId} /> ))} {isPending && <Loader />} <div ref={ref} /> </> ); }; 추가 질문 빌드 후 네트워크 탭에서 home 을 확인해보면 post 글 들이 모두 html로 변환되어 내려 오고 있습니다! (dev에서는 템플릿?으로 표현되더라고요) 저는 html이 아닌 데이터 형태로 내려와 useQuery로 해당 키로 접근해서 그냥 데이터를 가져올 줄 알았는데..그게 아닌가 보네요. 혹시 좀 더 자세히 설명 좀 부탁드려도 될까요?ㅠ 그리고 home 의 미리보기 탭에서는 post글들이 아닌 로딩 컴포넌트가 보입니다. (위의 사진에 응답 탭에서는 post글 들이 존재하고요) 로딩 컴포넌트가 보이는 이유는 하이드레이션이 처리되기 전이라 그런게 맞나요? 지금 자료를 다시 찾으려니 못 찾고 있는데.. suspense를 사용할 경우 완성된 화면이 아닌 로딩화면을 먼저 내려주므로 seo에는 나쁠 수 있다 라는 글을 본적이 있던 것 같은데..맞을까요? *SEO 관련해서 추가로 궁금한건 강의가 따로 있다고 영상에서 말씀하셔서 거기까지 보고 필요할 경우 질문 한번 더 드리겠습니다. 👍
오른쪽이 제화면이고 왼쪽이 선생님화면입니다. 현재상황: 기본명령어 commit, push, pull 1강부터 들으면서 example01 브렌치를 만들고 난후 pull하고 pr을 안한상태로 2강으로 넘어와 mable과 tree브렌치를 만들었습니다. 그리고 marge를 example01 into main을 눌렀더니 위와 같이 화면이 동그라미가 안생겼는데요. 머쥐를 취소 하기 위해 위와 같은 명령어를 썼는데도 안되서요. 혹시 선생님 화면처럼 동그라미를 만들기 위해서 어떻게 해야 하나요? mable브렌치로 퀘스트 실행했는데 현재 깃을 보면 아무것도 안나와서요. 깃주소는 : https://github.com/raikeni/test44 입니다.
안녕하세요 수업 너무 잘 듣고 있습니다. 수업을 듣다 궁금한점이 생겼는데 제가 인강을 보면서 변수 let, const와, 리액트에서 useState부분을 보고 이해는 갔지만 제가 막상 혼자 코드를 친다고 했을때 let, const와 useState를 언제 작성을 하면 되는지 잘 모르겠더라구요. 혼자 코드를 작성을 한다고 할때 변수와 useState를 언제 작성을 하면된다라고 이해를 하면 쉽게 이해할수있을까요?
안녕하세요 선생님 상세페이지에서 홈으로 이동할때 로딩화면에 관련해서 Link태그의 prefetching 질문있습니다. 아래와 같이 suspense를 적용했을때 app/(afterLoging)/home/page.tsx import style from './home.module.scss' import Tab from "@/app/(afterLogin)/home/_component/Tab"; import TabProvider from "@/app/(afterLogin)/home/_component/TabProvider"; import PostForm from "@/app/(afterLogin)/home/_component/PostForm"; import TabDeciderSuspense from '@/app/(afterLogin)/home//_component/TabDeciderSuspense'; import { Suspense } from 'react'; import Loading from './loading'; import { auth } from '@/auth'; export default async function Home() { const session = await auth(); return ( <main className={style.main}> <TabProvider> <Tab /> <PostForm me={session} /> {/* suspense는 서버컴포넌트여야만 한다. */} {/* suspense는 부모컴포넌트여야지 자식(아래)있는 컴포넌트 감지할 수 있다. */} <Suspense fallback={<Loading />}> <TabDeciderSuspense /> </Suspense> </TabProvider> </main> ); } next.js 문서를 보면 link태그가 있는 경우, 화면에 들어왔을때 static한 부분은 prefetch하고, 데이터 호출이 필요한 경우는 loading.tsx까지 호출해준다고 되어있더라구요. 그래서 제가 기대한 것은 상세페이지에서, 홈의 Link태그가 화면에 들어오기 대문에, 홈으로 이동했을때 첫번째 이미지가 아닌, 두번째 이미지처럼 로딩이 되어야할 것 같은데 첫번째 이미지 처럼 되더라구요. (이동한것도 30초 이내였습니다) 혹시 제가 잘못이해한건지 알려주시면 감사합니다. 유저 상세페이지에서 홈으로 이동할때 suspense적용후 새로고침하거나 팔로우중 클릭시
Supabase, Next 풀 스택 시작하기 (feat. 슈파베이스 OAuth, nextjs 14)
강의를 보고 같이 프로젝트도 만들어봤는데 문제가 생겨 글을 작성합니다. response 값을 확인하려고 네트워크 탭을 확인하니 프리플라이트가 같이 생성되고 클릭할 시 아래와 같은 메시지가 나옵니다. {"message":"No API key found in request","hint":"No apikey request header or url param was found."} 혹시 이 문제를 해결할 수 있는 방법을 알고 계신가요? 처음부터 supabase 설정을 다시 해야될까요?
팀원들과 토이프로젝트를 하다가 궁금한 git pull 과 관련하여 궁금증이 생겨서 질문드립니다... github에 원격 master 브랜치로부터 원격 dev 브랜치를 만들고 거기서 파생된 feature 작업브랜치에서 다시 개인 이름을 넣어 개인 작업 브랜치를 통해 로컬에서 작업했는데요. 이 때, 다른 팀원이 작업한 내용을 dev에 merge 했고 그 최신 내용을 제 로컬 작업브랜치에 추가로 가져오고 싶은데 이럴 때 어떻게 하면 좋을까요...? 먼저 로컬 dev 브랜치로 체크아웃을 하고 git pull origin dev 명령어를 통해 로컬 dev 브랜치를 최신화시켰습니다. 그 다음에 개인 로컬 작업 브랜치로 다시 체크아웃하고 git merge dev 를 통해 최신화된 로컬 dev 브랜치를 작업 브랜치에 병합시켰는데요. 커밋 해야할 내역을 보니 이전에 다른 팀원들이 원격에서 최신화한 내용들이 변경사항으로 들어가있더라구요... 그래서 그 부분까지 커밋하게되면 그 분들이 작업한 부분을 제 커밋메세지로 덮어쓸거같아서 걱정입니다.. 제가 어느 부분에서 잘못 진행한걸까요...?
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 ./ 이러한 명령어로 리액트를 설치했는데 이거와 전혀 다른 명령어 인가요?
login은 인터셉팅 라우터가 잘 되는데, signup은 (.)i로 인터셉팅이 안되고 버튼 클릭을 하면 그냥 i/flow/signup/page.tsx로만 보여지는 문제가 있습니다. 왜 signup은 인터셉팅 라우터가 작동이 안되는 것일까요?? 경로는 이렇게 잘 설정되어있고 안에 파일 내용은 아래와 같습니다. 아래는 @modal/(.)i/flow/signup/page.tsx 아래는 i/flow/signup/page.tsx 홈 버튼 링크는 아래와 같이 되어있습니다. 혹시 제가 빠뜨린 무엇이 있을까요?
안녕하세요. 강의 잘 보고 있습니다.!! 👍 👍 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] /home import 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;
geolocation부분에 const askForLocation = function () { navigator.geolocation.getCurrentPosition((position) => { console.log(position); }); }; askForLocation(); 이렇게 함수가 있는데 여기서 궁금한점이 askForLocation(); 함수 호출부분에 인자로 전달하는 것이 없는데 매개변수로 position에 위치정보 객체형식으로 콘솔에 나오는 이유가 뭔지 궁금합니다.
따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000 까지 하고 3000번 포트로 잘 들어가지는데 3000번포트를 지우고 들어가봐도 뒤에 :80을 붙여 넣어 들어가봐도 사이트에 연결할 수 없음이 뜨네요 왜 그럴까요??