묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (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"] });이런 식으로 업데이트를 하면 어떤 차이점이 있나요 ??데이터 업데이트시 쿼리를 업데이트 하고 리페칭하는 동작은 같은 것 같은데, 강의에서와 같이 복잡한 데이터 구조를 복사 해가며 구현하는 이유가 궁금합니다.성능상의 차이가 있는 것인가요 ??
-
미해결Next + React Query로 SNS 서비스 만들기
로그인 모달창 새로고침 시 배경 메인 페이지 사라지는 현상
로그인 버튼을 클릭하면 우선 '/login' 주소로 이동했다가 'i/flow/login'으로 이동하기 때문에 이때 '/login'에서 배경이 메인 컴포넌트를 보여줘야 메인 페이지가 바탕이 되고로그인 모달 창을 띄운다는 점은 이해했습니다.따라서 app/(beforeLogin)/login/page.tsx 에서 Main 컴포넌트를 보여주도록 했습니다.export default function Login() { const router = useRouter(); router.replace("/i/flow/login"); return <Main />; } 문제는 '/i/flow/login' 에서 새로고침하면 모달 창은 그대로지만 배경은 메인 페이지가 아닙니다. 이때 아래와 코드와 같이 따로 Main 컴포넌트를 불러오면 새로고침 시, 배경은 메인 페이지로 잘 나옵니다.그런데 강의와 깃허브 코드를 보니 LoginModal 컴포넌트만 보여주고 있습니다.LoginModal 컴포넌트만 있어도 app/(beforeLogin)/page.tsx에서 Main 컴포넌트를 보여주고 있으므로app/(beforeLogin)/layout.tsx에서 Main 컴포넌트가 {children}에 할당된다고 생각했습니다.따라서 아래 코드에서 Main 컴포넌트가 없어도 배경은 메인 페이지가 나온다고 생각했습니다. 아래 코드와 같이 Main 컴포넌트가 있으면 새로고침 시, 메인 페이지가 배경이 되고 그 위에 로그인 모달창이띄워지지만 Main 컴포넌트가 없으면 새로고침 시, 메인 페이지가 빈 페이지가 나옵니다. 여기서 Main 컴포넌트를 넣어서 해결해도 되는건지 의문이 들었습니다. 아래 코드에서 Main 컴포넌트를 넣지 않으면 Main 페이지가 어떻게 배경으로 보여지는 건지 알고 싶습니다!import LoginModal from "@/app/(beforeLogin)/@modal/(.)i/flow/login/page"; import Main from "@/app/(beforeLogin)/_component/Main"; export default function Page() { return ( <> <LoginModal /> <Main /> </> ); }
-
해결됨Next + React Query로 SNS 서비스 만들기
로그인 에러 질문입니다.
안녕하세요 제로초님 강의 듣던 중 동작이 원하는대로 안되어서 질문 드립니다.로그인 후 로그아웃 후 다른 아이디로 로그인 해도 로그아웃 버튼에는 전 계정의 정보가 뜹니다.아래는 로그인 모달의 코드입니다."use client"; import style from "@/app/(beforelogin)/_component/login.module.css"; import { ChangeEventHandler, FormEventHandler, useState } from "react"; import { redirect, useRouter } from "next/navigation"; import { signIn } from "next-auth/react"; export default function LoginModal() { const [id, setId] = useState(""); const [password, setPassword] = useState(""); const [message, setMessage] = useState(""); const router = useRouter(); const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => { e.preventDefault(); setMessage(""); try { const response = await signIn("credentials", { username: id, password, redirect: false, }); console.log(response, "1"); router.replace("/home"); console.log("2"); } catch (err) { console.error(err); setMessage("아이디와 비밀번호가 일치하지 않습니다."); } }; const onClickClose = () => { router.back(); }; const onChangeId: ChangeEventHandler<HTMLInputElement> = (e) => { setId(e.target.value); }; const onChangePassword: ChangeEventHandler<HTMLInputElement> = (e) => { setPassword(e.target.value); }; return ( <div className={style.modalBackground}> <div className={style.modal}> <div className={style.modalHeader}> <button className={style.closeButton} onClick={onClickClose}> <svg width={24} viewBox="0 0 24 24" aria-hidden="true" className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03" > <g> <path d="M10.59 12L4.54 5.96l1.42-1.42L12 10.59l6.04-6.05 1.42 1.42L13.41 12l6.05 6.04-1.42 1.42L12 13.41l-6.04 6.05-1.42-1.42L10.59 12z"></path> </g> </svg> </button> <div>로그인하세요.</div> </div> <form onSubmit={onSubmit}> <div className={style.modalBody}> <div className={style.inputDiv}> <label className={style.inputLabel} htmlFor="id"> 아이디 </label> <input id="id" className={style.input} value={id} onChange={onChangeId} type="text" placeholder="" /> </div> <div className={style.inputDiv}> <label className={style.inputLabel} htmlFor="password"> 비밀번호 </label> <input id="password" className={style.input} value={password} onChange={onChangePassword} type="password" placeholder="" /> </div> </div> <div className={style.message}>{message}</div> <div className={style.modalFooter}> <button className={style.actionButton} disabled={!id && !password}> 로그인하기 </button> </div> </form> </div> </div> ); } 아래는 로그아웃 버튼의 코드입니다. "use client"; import { useRouter } from "next/navigation"; import style from "./logoutButton.module.css"; import { signOut } from "next-auth/react"; import { Session } from "@auth/core/types"; type Props = { me: Session | null; }; export default function LogoutButton({ me }: Props) { const router = useRouter(); const onLogout = async () => { try { const response = await signOut({ redirect: false, }); console.log("signout", response); router.replace("/"); } catch (err) { console.log(err); } }; console.log("me", me); if (!me?.user) { return null; } return ( <button className={style.logOutButton} onClick={onLogout}> <div className={style.logOutUserImage}> <img src={me.user?.image as string} alt={me.user?.email as string} /> </div> <div className={style.logOutUserName}> <div>{me.user?.name}</div> <div>@{me.user?.email}</div> </div> </button> ); } 로그아웃 버튼에는 알려주신대로 레이아웃의 const session = await auth();session을 prop으로 내려주어서 사용하였습니다.처음 test 계정으로 로그인 했을 때의 콘솔을 찍어보면이렇게 test 계정이 정상적으로 나옵니다.이후 로그아웃 후에(session token 쿠키는 정상적으로 지워진 상태입니다) test4 계정으로 다시 로그인 하면이렇게 콘솔에 me 데이터가 test로 찍혀있고 test4의 정보가 로그아웃 버튼에 있습니다. 하지만 서버쪽 콘솔은 이렇게 test4로 나옵니다.이 상태에서 페이지 새로고침을 하면 정상적으로 로그아웃 버튼에는 test4의 데이터가 다시 들어가게 됩니다.로그아웃을 누를 때 세션 토큰이 정상적으로 지워지는 것을 확인했고, 재 로그인을 했는데 서버쪽에는 test4데이터가 찍히고 클라이언트 콘솔에는 test데이터가 찍히는 이유가 궁금합니다..2. 틀린 아이디 비밀번호를 입력했을 때에 제로초님과 응답이 다르게 날라옵니다.로그인 시에 틀린 아이디 비밀번호를 입력시에 저는 401에러가 아닌 이런 응답이 날라옵니다.이 부분은 에러인지 아니면 버전이 달라서 응답이 다른 것 인지는 잘 모르겠습니다. error는 credentialSignIn으로 날라오지만 ok와 status는 true에 200으로 날라오는데, 버전차이인가요 ..? next-auth 버전은 5.0.0-beta.17 입니다.
-
미해결Next + React Query로 SNS 서비스 만들기
api호출 3초뒤로 하고, loading.tsx 파일이 있을 때 없을때 /home/page.tsx
안녕하세요 제로초님제목처럼api호출 3초뒤로 하고, loading.tsx 파일이 있을 때 없을때 /home/page.tsx이런식으로 테스트를 해봤습니다. /home/page.tsx에서는 react-query로 ssr을 적용했고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 { HydrationBoundary, QueryClient, dehydrate } from '@tanstack/react-query'; import TabDecider from "@/app/(afterLogin)/home/_component/TabDecider"; import { getPostRecommends } from '@/app/(afterLogin)/_lib/getPostRecommends'; export default async function Home() { const queryClient = new QueryClient(); await queryClient.prefetchInfiniteQuery({ queryKey: ['posts', 'recommends'], queryFn: getPostRecommends, initialPageParam: 0, }); const dehydratedState = dehydrate(queryClient); return ( <main className={style.main}> <HydrationBoundary state={dehydratedState}> <TabProvider> <Tab /> <PostForm /> <TabDecider /> </TabProvider> </HydrationBoundary> </main> ); } /mocks/handlers.tsx에서는 postRecommends를 가져오되 3초 delay를 줬습니다.http.get('/api/postRecommends', async ({ request }) => { console.log('----------------------------------handlers /api/postRecommends'); await delay(3000); const url = new URL(request.url); const cursor = parseInt(url.searchParams.get('cursor') as string) || 0; return HttpResponse.json( [ { postId: cursor + 1, User: User[0], content: `${cursor + 1} ${faker.lorem.paragraph()}`, Images: [{ imageId: 1, link: faker.image.urlLoremFlickr({ category: 'animals' }) }], createdAt: generateDate(), }, { postId: cursor + 2, User: User[0], content: `${cursor + 2} ${faker.lorem.paragraph()}`, Images: [ { imageId: 1, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, { imageId: 2, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, ], createdAt: generateDate(), }, { postId: cursor + 3, User: User[0], content: `${cursor + 3} ${faker.lorem.paragraph()}`, Images: [], createdAt: generateDate(), }, { postId: cursor + 4, User: User[0], content: `${cursor + 4} ${faker.lorem.paragraph()}`, Images: [ { imageId: 1, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, { imageId: 2, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, { imageId: 3, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, { imageId: 4, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, ], createdAt: generateDate(), }, { postId: cursor + 5, User: User[0], content: `${cursor + 5} ${faker.lorem.paragraph()}`, Images: [ { imageId: 1, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, { imageId: 2, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, { imageId: 3, link: faker.image.urlLoremFlickr({ category: 'animals' }) }, ], createdAt: generateDate(), }, ] ); }), 이 후에 ssr화면 테스트를 위해서브라우저의 자바스크립트 사용중지 했습니다.서버도 각각 재시작하고 테스트했습니다.그리고 나서 테스트한 화면입니다.아래 화면은 loading.tsx가 업을때,아래 화면은 loading.tsx가 있을때 입니다.선생님 강의에서ssr을 적용했을때 loading화면을 포기해야한다고 이해했었습니다.prefetchInfiniteQuqery를 쓰고 loading을 포기하거나, prefetchInfiniteQuqery을 포기하고 loading을 사용하거나.그런데 제가 테스트했을때는 ssr이라도 로딩 화면이 보이는걸로 봐서 제가 테스트를 잘못한건지,loading.tsx가 있는것 자체가 suspense를 사용한것과 동일한 효과를 주어서 보여지게 되는건지여쭙고 싶습니다. 제가 잘못테스트했다면 어떻게 테스트를 해야 좀 더 정확히 구분지을 수있을지도 궁금합니다.
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
해결했습니다!
해결했습니다!
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
안드로이드에서만 테마별 색상이 적용안되는 이유
안드로이드 기기에서, 테마에 해당하는 색상을 못읽는 에러가 발생합니다!!iOS 같은 경우는 정상적으로 다크모드가 잘 동작합니다!!! 어떤 부분이 문제인지 알고 싶습니다. https://github.com/dydals3440/MatZip
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
useEffect 의존성 배열 문제
해당 강좌 그대로 진행하다가, 의존성 배열 문제로 인해 무한 렌더링이 발생했습니다.강사님의 깃허브 코드를 바탕으로, 강좌와 다르게 전역 상태로 관리를 진행하여 해결을 하긴 했습니다.어떠한 문제로 인해, 무한 렌더링이 발생되고, 이럴 경우에 어떤 방식으로 접근해서 해결하는지에 대한 접근 방식에 대해 알고 싶습니다!!!web과 다르게 RN은 디버깅하기가 생각보다 쉽지않네요... ㅠㅠ
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
의존성 배열에 filterItems를 넣으면 무한렌더링이 발생합니다.
import {useEffect, useState} from 'react'; import {queryKeys, storageKeys} from '@/constants'; import type {Marker} from '@/types'; import {getEncryptedStorage, setEncryptedStorage} from '@/utils'; import queryClient from '@/api/query-client'; const initialFilters = { RED: true, YELLOW: true, GREEN: true, BLUE: true, PURPLE: true, '1': true, '2': true, '3': true, '4': true, '5': true, }; function useMarkerFilterStorage() { const [filterItems, setFilterItems] = useState<Record<string, boolean>>(initialFilters); const set = async (items: Record<string, boolean>) => { queryClient.invalidateQueries({ queryKey: [queryKeys.MARKER, queryKeys.GET_MARKERS], }); await setEncryptedStorage(storageKeys.MARKER_FILTER, items); setFilterItems(items); }; const transformFilteredMarker = (markers: Marker[]) => { return markers.filter(marker => { return ( filterItems[marker.color] === true && filterItems[String(marker.score)] === true ); }); }; useEffect(() => { (async () => { const storedData = (await getEncryptedStorage(storageKeys.MARKER_FILTER)) ?? initialFilters; setFilterItems(storedData); })(); }, [filterItems]); return {set, items: filterItems, transformFilteredMarker}; } export default useMarkerFilterStorage;의도대로 items의 값을 set으로 변경하면 필터링이 정상적으로 동작하지만 무한렌더링이 발생합니다.무한 렌더링을 막기 위해 의존성 배열을 지우고 쿼리키를 무효화하는 방법등 많은 시도를 해봤지만 제대로 동작하지 않네요. 혹시 현재 진행된 강의에서 무한 렌더링을 해결할 수 있는 방법이 있을까요?
-
미해결Next + React Query로 SNS 서비스 만들기
The Middleware "/src/middleware" must export a middleware or a default function
미들웨어 matcher에 추가한 페이지 home으로 replace 시에 이렇게 에러가 뜨는데 이유를 모르겠습니다 ㅠ⨯ Error [ERR_HTTP_HEADERS_SENT]: Cannot append headers after they are sent to the clientat ServerResponse.appendHeader (node:_http_outgoing:689:11)at AsyncLocalStorage.run (node:async_hooks:346:14) import { auth as middleware } from "./auth"; export const config = { matcher: ["/compose/tweet", "/home", "/explore"], };
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
react-native-date-picker darkmode 적용 관련 공유
다크모드를 어떻게 적용시킬까 고민하다가, 찾아보니 theme이라는 프로퍼티를 사용해서 아래와 같이 코드를 작성하면 다크모드가 적용이 됩니다!! import {colors} from '@/constants'; import useThemeStore from '@/store/useThemeStore'; import {ThemeMode} from '@/types/common'; import React from 'react'; import { StyleSheet, View, Modal, SafeAreaView, Pressable, Text, } from 'react-native'; import DatePicker from 'react-native-date-picker'; interface DatePickerOptionProps { isVisible: boolean; date: Date; onChangeDate: (date: Date) => void; onConfirmDate: () => void; } const DatePickerOption = ({ isVisible, date, onChangeDate, onConfirmDate, }: DatePickerOptionProps) => { const {theme} = useThemeStore(); const styles = styling(theme); return ( <Modal visible={isVisible} transparent animationType="slide"> <SafeAreaView style={styles.optionBackground}> <View style={styles.optionContainer}> <View style={styles.pickerContainer}> <DatePicker mode="date" date={date} onDateChange={onChangeDate} locale="ko" theme={theme === 'dark' ? 'dark' : 'light'} /> </View> </View> <View style={styles.optionContainer}> <Pressable style={styles.optionButton} onPress={onConfirmDate}> <Text style={styles.optionText}>확인</Text> </Pressable> </View> </SafeAreaView> </Modal> ); }; const styling = (theme: ThemeMode) => StyleSheet.create({ pickerContainer: { alignItems: 'center', }, optionBackground: { flex: 1, justifyContent: 'flex-end', backgroundColor: 'rgba(0, 0, 0 / 0.5)', }, optionContainer: { borderRadius: 15, marginHorizontal: 10, marginBottom: 10, backgroundColor: colors[theme].GRAY_100, overflow: 'hidden', }, optionButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: 50, gap: 5, }, optionText: { color: colors[theme].BLUE_500, fontSize: 17, fontWeight: '500', }, }); export default DatePickerOption;
-
미해결Next + React Query로 SNS 서비스 만들기
msw 모바일 환경으로 local 접속 에러
localhost 환경에서 모바일로 접속 하였을때 IP 주소 확인하여 넣어줬는데도 api error가 발생하는데 이유를 잘 모르겠습니다.app.use( cors({ origin: 'http://내 IP 주소:3000', optionsSuccessStatus: 200, credentials: true }) );
-
미해결Next + React Query로 SNS 서비스 만들기
msw text/event-stream 질문
안녕하세요. 강의를 다 듣고 혼자 프로젝트를 진행해보고 있는 중인데 궁금한 것이 생겨 질문 드립니다!msw로 모킹하여 스트림데이터를 넘겨주고, 브라우저에 데이터가 나타날 때 gpt 답변처럼 한글자씩 보여지게 처리하고 싶은데 공식문서를 봐도 잘 안되네요..(한글자씩 안 나오고 한번에 나타남) 감사합니다.버전 : msw 2.0참고 문서 : https://mswjs.io/docs/recipes/streaming/
-
해결됨Next + React Query로 SNS 서비스 만들기
Suspense와 prefetch 관련 질문이 있습니다.
안녕하세요 제로초님! 강의를 듣던 중 궁금한게 생겨서 질문 드립니다. TabDeciderSuspense 컴포넌트를 사용하는 것을 보았습니다.원래는 postRecommends의 데이터를 프리페칭해서 서버에서 데이터를 페칭하고 클라이언트에서 하이드레이션 하고있었는데, suspense를 사용해버리면 서버에서 프리페칭이 되는건지 궁금합니다.suspense를 적용하고 나서 페이지 새로고침 후에 페이지 document를 보면이렇게 prefetch한 데이터가 있는 것이 아니라 loading이 넘어와 있습니다.원래는 서버에서 prefetch한 데이터가 document로 넘어왔는데, suspense 적용 후 로딩스피너가 넘어 온 것으로 보아 suspense를 적용하면 prefetch가 되지 않는 것 인가요 ?? 그것이 아니라면 suspense를 적용하고 prefetch를 사용하는 이유가 궁금합니다.
-
해결됨[리뉴얼] 맛집 지도앱 만들기 (React Native & NestJS)
최근 DatePicker의 textColor prop이 제거되었고, theme 사용이 권장됩니다.
버그나 에러 질문은 아니구요! react native date picker 패키지를 이용해 DatePicker를 구현하는 단계있는데요,textColor prop을 타이핑할 때 자동완성이 안되어 찾아보니 올해 3월 23일에 릴리즈한 5.0.0에서 제거되었네요. https://github.com/henninghall/react-native-date-picker/releases/tag/5.0.0대신 theme을 사용하라고 하는데, 기본값인 auto를 쓰거나 혹은 light로 설정하면 강의와 같이 text가 검은색으로 잘 나옵니다.강의 들으시다가 저처럼 띠용하시는 분 계실까봐 참고차 남겨놓습니다! 좋은 강의 감사드립니다!
-
미해결Next + React Query로 SNS 서비스 만들기
next-auth 질문 + 새소식 올려주신거 참고해서 await signIn('credentials', { ...data, redirect: true });수정한후 로그인 후 홈으로 이동안됩니다.
안녕하세요 선생님새소식 올려주신거 참고해서 await signIn('credentials', { ...data, redirect: true });수정한후 로그인 후 홈으로 이동안됩니다.home 갔다가 로그인화면으로 이동해버리는데 어디서 이동시키는건지 뒤저봐도 못 찾겠더라구요. 로그인화면으로 새로고침되는듯 합니다...true만 하고 이전 코드와 다 똑같은데 조언 부탁드립니다 ㅠ/src/app/(beforeLogin)/_component/Loginmodal.tsxconst onSubmit: SubmitHandler<formProps> = async (data: formProps) => { console.log(data); try { await signIn('credentials', { ...data, redirect: true }); router.replace('/home'); console.log('---------------------------------------after LoginModal login') } catch(error) { console.error(error); console.log('아이디와 비밀번호가 일치히자 않습니다.'); } }; src/middleware.tsexport async function middleware() { const session = await auth(); console.log(session, '------------------------------middleware session') if (!session) { return NextResponse.redirect('http://localhost:3001/i/flow/login'); } } // See 'Matching Paths' below to lean more // 미들웨어를 적용할 라우트로 로그인을 해야하는 페이지 // 페이지 접근관리 하기 쉬워짐 export const config = { matcher: ['/compose/tweet', '/home', '/explore', '/messages', '/search'] } /src/auth.tsimport NextAuth, {CredentialsSignin} from "next-auth" // import CredentialsProvider from "next-auth/providers/credentials" import Credentials from "next-auth/providers/credentials" import { NextResponse } from 'next/server'; export const { // api 라우트 handlers: { GET, POST }, // auth 함수 실행하면 로그인 유무알 수 있다. auth, // 로그인 하는 함수 signIn } = NextAuth({ pages: { signIn: "/i/flow/login", newUser: '/i/flow/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('-------------------------------------------auth.ts'); 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.status, authResponse.statusText) if (!authResponse.ok) { const credentialsSignin = new CredentialsSignin(); if (authResponse.status === 404) { credentialsSignin.code = 'no_user'; } else if (authResponse.status === 401) { credentialsSignin.code = 'wrong_password'; } throw credentialsSignin; } // 로그인 성공 const user = await authResponse.json(); console.log('user', user); // return user object with the their profile data return { ...user, name: user.nickname, email: user.id, } }, }), ] }) next-auth 소식이나 말쓰하시는거 들어봐도 아직 안정화가 되지 않은것같은데 선생님은 next-auth를 실무에 도입해도 된다고보시나요? 아니면 nodebird 처럼 express로 하는걸 더 추천하실지 궁금합니다. 넥스트오쓰에서 가입한 사용자를 데이터베이스로 볼수있는지도 궁금하구 어차피 배워야할것이니 이런저런 부족한게 좀 있더라도 밀고나가야하는지.. 여유되실때 확인해주시면 감사하겠습니다.