묻고 답해요
143만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
카카오 공유했을 때 이전에 작성했던 글이 나오는 버그
안녕하세요 선생님보너스 강의 전까지 보고 카카오 공유하기 까지 테스트하고 있는데버그를 발견한것 같아서 어떻게 해결할지 여쭤보려 올립니다.위처럼 post/5의 게시글을 작성하고카카오톡에 공유를 하면이전에 썼던 (로컬에서 썼었던) 내용이 보여집니다.혹시 기존 데이터베이스를 리셋하거나 추가적인 작업이 필요한건지 궁금합니다.
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
검색어 입력 후 초기화하는 방법 궁금합니다!
안녕하세요. 강의 수강 중에 추가적으로 구현하고 싶은 기능이 있는데 어떻게 해야할지 모르겠어서.. 질문 남깁니다. 검색창에 검색어를 입력하면 SearchPage에 관련 영화 포스터들이 나오고 그 중에 하나를 클릭해서 영화 상세 페이지(DetailPage)로 이동했을 때 검색창을 초기화하고 싶은데 어떻게 해야 하는지 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
searchParams props
안녕하세요search 페이지 props에서 searchParams props가 기본적으로 제공된다고 알고있는데 저는 콘솔로 찍어보니 나오지 않습니다..! 혹시 제가 잘못적용한건지 아니면 다시한번 확인해야 될곳이 있을까요?/import SelectBox from "@/components/common/SelectBox"; import SelectStack from "@/components/common/SelectStack"; import Peoples from "@/components/people/Peoples"; import SearchForm from "@/components/common/SearchForm"; type Props = { searchParams: { page: string; size: string; sort?: string; keyword?: string; position?: string; teckStack?: string; }; }; export default function Page({ searchParams }: Props) { console.log("??", searchParams); return ( <div> <div className="relative flex items-center gap-4"> <h1 className="text-[36px] font-bold">People</h1> </div> <div className="flex justify-between"> <div className="flex gap-3"> <SelectBox options={option} title="포지션" /> <SelectStack /> </div> <SearchForm keyword={searchParams.keyword as string} /> </div> <Peoples searchParams={searchParams} /> </div> ); }
-
미해결Next + React Query로 SNS 서비스 만들기
하트 클릭 시 Hearts 배열 업데이트 관련 질문
하트 버튼을 눌러서 Heart 배열에 userId를 넣어줄 때Hearts: [...value.pages[pageIndex][index].Hearts, { userId: session?.user?.email as string }],위와 같이 기존 Hearts 배열에 본인 userId 값을 추가하는 방식이 아니라Hearts: [{ userId: session?.user?.email as string }],이렇게 Hearts 배열에 본인 userId 값만 넣어주는 이유는 무엇인가요? 어차피 보여지는 결과는 동일하기 때문에 굳이 배열을 복사하는 과정을 거치지 않아 성능을 높이기 위함이라고 보면 될까요?
-
미해결Next + React Query로 SNS 서비스 만들기
프리즈마로 api만드시는 강의는 언제쯤 나올지 알 수 있을까요?
안녕하세요 선생님프리즈마로 api만드시는 강의는 언제쯤 나올지 알 수 있을까요?직접만든 api랑 이번수업에서 배울next로 플젝을 만들고 싶은데 궁금합니다.
-
미해결next 14.2 최신버전 공식문서 파먹기
<Link> 사용유무
Link 태그안에 a 태그가 내장되어있는데, 그럼 내부 라우트간의 이동에만 Link를 쓰고, 외부 링크 연결에만 a 태그를 쓰시나요? 아니면 무조건 Link로만 사용하시나요?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
프론트서버 배포 후 EADDRINUSE에러 발생
안녕하세요 제로초님덕분에 front배포 잘 하게 되었습니다.그후 접속해서 테스트했는데, 회원가입할 때 connect_refused가 발생해 로그를 찾아보았습니다.EADDRINUSE를 발견하고 원인을 찾으려고 뒤져봤는데 해결되지 않아 여쭤봅니다. ㅠfront = 13.125.119.94 back = 13.125.252.5 아래는 설정한 내용/front/package.json"scripts": { "dev": "next dev", "build": "cross-env ANALYZE=true NODE_ENV=production next build", "start": "cross-env NODE_ENV=production next start -p 80", }, /back/packge.json"scripts": { "dev": "nodemon app", "start": "cross-env NODE_ENV=production pm2 start app.js" }, /back/app.js// node에서는 import / export 안쓰고 require / module.exports 사용 const express = require('express'); const cors = require('cors'); const session = require('express-session'); const cookieParser = require('cookie-parser'); const passport = require('passport'); const dotenv = require('dotenv'); const morgan = require('morgan'); const path = require('path'); const hpp = require('hpp'); const helmet = require('helmet'); const postRouter = require('./routes/post'); const postsRouter = require('./routes/posts'); const userRouter = require('./routes/user'); const hashtahRouter = require('./routes/hashtag'); const db = require('./models'); // sequelize에서 model 모두 등록 // express에서 그 sequelize를 등록해야 한다. const passportConfig = require('./passport'); dotenv.config(); const app = express(); db.sequelize .sync() .then(() => { console.log('db연결 성공!'); }) .catch(console.error); passportConfig(); // 운영용 빌드 if (process.env.NOD_ENV === 'production') { app.use(morgan('combined')); // 로그볼 수 있게 해주는 것 // 보안에 도움되는 패키지들 app.use(hpp()); app.use(helmet()); } else { app.use(morgan('dev')); // 로그볼 수 있게 해주는 것 } app.use( cors({ origin: ['http://localhost:3000', 'nodebird.com', 'http://13.125.119.94'], credentials: true, }) ); app.use('/', express.static(path.join(__dirname, 'uploads'))); app.use(express.urlencoded({ extended: true })); app.use(cookieParser(process.env.COOKIE_SECRET)); app.use( session({ saveUninitialized: false, resave: false, secret: process.env.COOKIE_SECRET, }) ); app.use(passport.initialize()); app.use(passport.session()); app.use('/post', postRouter); app.use('/posts', postsRouter); app.use('/user', userRouter); app.use('/hashtag', hashtahRouter); app.listen(80, () => { console.log('서버 실행 중'); }); 프론트 실행화면백엔드 실행 화면 아래는 에러 내용입니다./front 에러AxiosError: connect ECONNREFUSED 13.125.252.5:443 0|npm | at AxiosError.from (file:///home/ubuntu/react-nodebird/prepare/front/node_modules/axios/lib/core/AxiosError.js:89:14) 0|npm | at RedirectableRequest.handleRequestError (file:///home/ubuntu/react-nodebird/prepare/front/node_modules/axios/lib/adapters/http.js:610:25) 0|npm | at RedirectableRequest.emit (node:events:517:28) 0|npm | at eventHandlers.<computed> (/home/ubuntu/react-nodebird/prepare/front/node_modules/follow-redirects/index.js:38:24) 0|npm | at ClientRequest.emit (node:events:517:28) 0|npm | at TLSSocket.socketErrorListener (node:_http_client:501:9) 0|npm | at TLSSocket.emit (node:events:517:28) 0|npm | at emitErrorNT (node:internal/streams/destroy:151:8) 0|npm | at emitErrorCloseNT (node:internal/streams/destroy:116:3) 0|npm | at process.processTicksAndRejections (node:internal/process/task_queues:82:21) 0|npm | at Axios.request (file:///home/ubuntu/react-nodebird/prepare/front/node_modules/axios/lib/core/Axios.js:45:41) 0|npm | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) 0|npm | at async y (/home/ubuntu/react-nodebird/prepare/front/.next/server/chunks/414.js:1:1838) { 0|npm | port: 443, 0|npm | address: '13.125.252.5', 0|npm | syscall: 'connect', 0|npm | code: 'ECONNREFUSED', 0|npm | errno: -111, 0|npm | config: { 0|npm | transitional: { 0|npm | silentJSONParsing: true, 0|npm | forcedJSONParsing: true, 0|npm | clarifyTimeoutError: false 0|npm | }, cause: Error: connect ECONNREFUSED 13.125.252.5:443 0|npm | at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16) { 0|npm | errno: -111, 0|npm | code: 'ECONNREFUSED', 0|npm | syscall: 'connect', 0|npm | address: '13.125.252.5', 0|npm | port: 443 0|npm | } back 에러 | Warning: connect.session() MemoryStore is not 0|app | designed for a production environment, as it will leak 0|app | memory, and will not scale past a single process. 0|app | Error: listen EADDRINUSE: address already in use / 0|app | at Server.setupListenHandle [as _listen2] (node:net:1800:21) 0|app | at listenInCluster (node:net:1865:12) 0|app | at Server.listen (node:net:1964:5) 0|app | at Function.listen (/home/ubuntu/react-nodebird/prepare/back/node_modules/express/lib/application.js:635:24) 0|app | at Object.<anonymous> (/home/ubuntu/react-nodebird/prepare/back/app.js:75:5) 0|app | at Module._compile (node:internal/modules/cjs/loader:1364:14) 0|app | at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) 0|app | at Module.load (node:internal/modules/cjs/loader:1203:32) 0|app | at Module._load (node:internal/modules/cjs/loader:1019:12) 0|app | at Object.<anonymous> (/home/ubuntu/react-nodebird/prepare/back/node_modules/pm2/lib/ProcessContainerFork.js:33:23) { 0|app | code: 'EADDRINUSE', 0|app | errno: -98, 0|app | syscall: 'listen', 0|app | address: '/', 0|app | port: -1 0|app | } front monit back monit 비슷한 질문들이 올라와 있어서 (sudo) npx pm2 kill 해보거나 다른 검색들을 해봤는데 원인을 모르겠더라구요어떤 부분을 수정해야할지 어떤부분을 확인해봐야할지 봐주시면 정말 감사하겠습니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
react hooks 포트폴리오 리펙토링 질문
import { Modal } from "antd"; import DaumPostcodeEmbed from "react-daum-postcode"; import * as S from "./BoardWrite.style"; import UploadImage from "../../../commons/uploadImage/uploadImage.container"; import { v4 as uuidv4 } from "uuid"; import { useBoard } from "../../../commons/hooks/customs/useBoard"; import { useCheckedId } from "../../../commons/hooks/customs/useCheckedId"; import { useForm } from "react-hook-form"; import { useToggle } from "../../../commons/hooks/customs/useToggle"; import { useEffect, useState } from "react"; import type { IBoardWriteProps } from "./BoardWrite.types"; import { useAuth } from "../../../commons/hooks/customs/useAuth"; export interface Iform { writer: string; password: string; title: string; contents: string; boardAddress: { zipcode: string; address: string; addressDetail: string; }; youtubeUrl: string; images: string[]; } export default function BoardWrite(props: IBoardWriteProps): JSX.Element { useAuth(); const { id } = useCheckedId("boardId"); const { onClickWrite, onClickEdit, onChangePassword } = useBoard({ boardId: id, }); const [files, setFiles] = useState(["", "", ""]); // const [isActive] = useToggle(); const [isOpenModal, modalToggle] = useToggle(); // 게시글 작성 안했을시 오류 보여주는 state const [Error] = useState(""); const { register, handleSubmit, setValue } = useForm<Iform>(); useEffect(() => { if (props.data) { setValue("writer", props.data.fetchBoard.writer ?? ""); setValue("title", props.data.fetchBoard.title ?? ""); setValue("contents", props.data.fetchBoard.contents ?? ""); setValue( "boardAddress.zipcode", props.data.fetchBoard.boardAddress?.zipcode ?? "" ); setValue( "boardAddress.address", props.data.fetchBoard.boardAddress?.address ?? "" ); setValue( "boardAddress.addressDetail", props.data.fetchBoard.boardAddress?.addressDetail ?? "" ); setValue("images", props.data.fetchBoard.images ?? ["", "", ""]); } const images = props.data?.fetchBoard.images; if (images !== undefined && images !== null) setFiles([...images]); }, [props.data]); const onChangeFiles = (file: string, index: number): void => { // file값은 url값 index는 해당하는 number값. const newFiles = [...files]; newFiles[index] = file; setFiles(newFiles); setValue("images", newFiles); }; return ( <S.Wrapper> <S.BoardTitle>게시글 {props.isEdit ? "수정" : "등록"}</S.BoardTitle> <S.WriterSection> <S.HalfSection> <S.BoardLabel>작성자</S.BoardLabel> <S.BoardInput type="text" defaultValue={props.data?.fetchBoard.writer ?? ""} placeholder="작성자를 입력해주세요" {...register("writer")} /> <S.Error>{Error}</S.Error> </S.HalfSection> <S.HalfSection> <S.BoardLabel>비밀번호</S.BoardLabel> <S.BoardInput type="password" placeholder="비밀번호를 입력해주세요." {...register("password")} onChange={onChangePassword} /> <S.Error>{Error}</S.Error> </S.HalfSection> </S.WriterSection> <S.Section> <S.BoardLabel>제목</S.BoardLabel> <S.BoardInput type="text" placeholder="제목을 입력해주세요" {...register("title")} /> <S.Error>{Error}</S.Error> </S.Section> <S.Section> <S.BoardLabel>내용</S.BoardLabel> <S.BoardContents id="title" placeholder="내용을 입력해주세요" {...register("contents")} ></S.BoardContents> <S.Error>{Error}</S.Error> </S.Section> <S.Section> <S.BoardLabel>주소</S.BoardLabel> <S.ZipCodeWrapper> <S.ZipCodeInput placeholder="07725" readOnly {...register("boardAddress.zipcode")} /> <S.ZipCodeButton onClick={modalToggle}> 우편번호 검색 {/* 모달창의 state를 받아와서 true라면 모달창을 열어준다. */} {isOpenModal && ( <Modal open={isOpenModal}> <DaumPostcodeEmbed onComplete={(data) => { setValue("boardAddress.zipcode", data.zonecode); setValue("boardAddress.address", data.address); modalToggle(); }} /> </Modal> )} </S.ZipCodeButton> </S.ZipCodeWrapper> <S.Address readOnly {...register("boardAddress.address")} /> <S.Address type="text" placeholder="상세주소를 입력해주세요" {...register("boardAddress.addressDetail")} /> </S.Section> <S.Section> <S.BoardLabel>유튜브</S.BoardLabel> <S.BoardInput type="text" placeholder="링크를 복사해주세요" {...register("youtubeUrl")} /> </S.Section> <S.Section> <S.BoardLabel>사진 첨부</S.BoardLabel> {/* 이미지 업로드 컴포넌트 분리 */} <S.ImageWrapper> {files.map((el, index) => ( <UploadImage key={uuidv4()} files={el} // 여기로 들어온 el값은 ""값 기본값이기 때문에 index={index} onChangeFiles={onChangeFiles} /> ))} </S.ImageWrapper> </S.Section> <S.Section> <S.BoardLabel>메인 설정</S.BoardLabel> <S.RadioButton type="radio" id="youtube" name="radio-button" /> <S.RadioLabel htmlFor="youtube">유튜브</S.RadioLabel> <S.RadioButton type="radio" id="image" name="radio-button" /> <S.RadioLabel htmlFor="image">사진</S.RadioLabel> </S.Section> <S.RegistButton onClick={handleSubmit(props.isEdit ? onClickEdit : onClickWrite)} isEdit={props.isEdit} > {props.isEdit ? "수정" : "등록"}하기 </S.RegistButton> </S.Wrapper> ); }포트폴리오 리펙토링을 진행하다가 useForm의 defaultValue를 사용할때 텍스트 데이터는 잘 들어오다가modal창의 주소 데이터나 images 배열은 제대로 들어오지 않아서 방법을 찾다가 setValue를 이용해서 값을 넣어주는 방법이 있어서 이렇게 작성해봤는데 useEffect를 이용해서 만들어봤는데 setValue는 setState와 같은 기능을 하는것같아서 이런식으로하면 리렌더링의 문제가 없는지 궁금합니다
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
npm run build 에러
안녕하세요 제로초님프론트 서버를 npm run build 하니까아래와 같은 에러가 나오는데검색해서 찾아봐도 잘 모르겠더라구요.혹시 어느 부분을 확인해보고 어떤 부분을 수정해야할지 조언해주실 수 있을까요?빌드하는것만 몇일째라 ㅠ답답합니다. Collecting page data ./home/ubuntu/react-nodebird/prepare/front/node_modules/rc-util/es/omit.js:1 import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; ^^^^^^ SyntaxError: Cannot use import statement outside a module at internalCompileFunction (node:internal/vm:76:18) at wrapSafe (node:internal/modules/cjs/loader:1283:20) at Module._compile (node:internal/modules/cjs/loader:1328:27) at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) at Module.load (node:internal/modules/cjs/loader:1203:32) at Module._load (node:internal/modules/cjs/loader:1019:12) at Module.require (node:internal/modules/cjs/loader:1231:19) at mod.require (/home/ubuntu/react-nodebird/prepare/front/node_modules/next/dist/server/require-hook.js:65:28) at require (node:internal/modules/helpers:177:18) at 5514 (/home/ubuntu/react-nodebird/prepare/front/.next/server/pages/signup.js:7:10601) /home/ubuntu/react-nodebird/prepare/front/node_modules/rc-util/es/omit.js:1 import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; ^^^^^^ SyntaxError: Cannot use import statement outside a module at internalCompileFunction (node:internal/vm:76:18) at wrapSafe (node:internal/modules/cjs/loader:1283:20) at Module._compile (node:internal/modules/cjs/loader:1328:27) at Module._extensions..js (node:internal/modules/cjs/loader:1422:10) at Module.load (node:internal/modules/cjs/loader:1203:32) at Module._load (node:internal/modules/cjs/loader:1019:12) at Module.require (node:internal/modules/cjs/loader:1231:19) at mod.require (/home/ubuntu/react-nodebird/prepare/front/node_modules/next/dist/server/require-hook.js:65:28) at require (node:internal/modules/helpers:177:18) at 5514 (/home/ubuntu/react-nodebird/prepare/front/.next/server/pages/signup.js:7:10601) > Build error occurred Error: Failed to collect page data for /signup at /home/ubuntu/react-nodebird/prepare/front/node_modules/next/dist/build/utils.js:1268:15 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { type: 'Error' } /pages.index.jsimport axios from 'axios'; import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import AppLayout from '../components/AppLayout'; import PostCard from '../components/PostCard'; import PostForm from '../components/PostForm'; import { loadPosts, loadPostsError } from '../reducers/post'; import { loadMyInfo } from '../reducers/user'; import wrapper from '../store/configurStore'; // 프론트, 브라우저 같이 실행 const Home = () => { const { me } = useSelector((state) => state.user); const { mainPosts, hasMorePosts, loadPostsLoading, retweetError } = useSelector((state) => state.post); const dispatch = useDispatch(); useEffect(() => { if (retweetError) { alert(retweetError); } }, [retweetError]); useEffect(() => { const onScroll = () => { if ( window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300 ) { if (hasMorePosts && !loadPostsLoading) { const lastId = mainPosts[mainPosts.length - 1]?.id; dispatch(loadPosts({ lastId, limit: 10 })); } } }; window.addEventListener('scroll', onScroll); return () => { window.removeEventListener('scroll', onScroll); }; }, [hasMorePosts, loadPostsLoading, mainPosts.length]); return ( <AppLayout> {me && <PostForm />} {mainPosts && mainPosts[0] ? mainPosts.map((post) => <PostCard key={post.id} post={post} />) : null} </AppLayout> ); }; export const getServerSideProps = wrapper.getServerSideProps( (store) => async ({ req }) => { console.log('getServerSideProps start--------------------------'); console.log(req.headers); const cookie = req ? req.headers.cookie : ''; axios.defaults.headers.Cookie = ''; // 쿠키가 브라우저에 있는경우만 넣어서 실행 // (주의, 아래 조건이 없다면 다른 사람으로 로그인 될 수도 있음) if (req && cookie) { axios.defaults.headers.Cookie = cookie; } await store.dispatch(loadPosts()); await store.dispatch(loadMyInfo()); }, ); export default Home;
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
front 서버 npm run build 중에 발생한 에러들
안녕하세요 제로초님front 서버를 빌드하던중에 빌드가 된줄알고 pm2 monit으로 확인해보니 Could not find a production build in the '.next' directory 이런 에러가 떠있었습니다. 확인해봤더니 아래와 같은 에러 들이 엄청 나오더라구요.warning도 아니고 다 error들이라 검색해보고 .eslintrc를 고쳐봤는데도 잘 안되서 여쭤봅니다 ㅠ 다른 분들은 이런 에러 없이 잘 되는거같은데 전 왜이런지 도와주시면 감사하겠습니다 ㅠ ㅠ npm run build 했을때 나타나는 에러중 일부/components/LoginForm.js 11:1 Error: Unexpected tab character. no-tabs 14:1 Error: Unexpected tab character. no-tabs 17:19 Error: Function component is not a function declaration react/function-component-definition 18:1 Error: Unexpected tab character. no-tabs 18:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 19:1 Error: Unexpected tab character. no-tabs 19:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 20:1 Error: Unexpected tab character. no-tabs 20:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 21:1 Error: Unexpected tab character. no-tabs 21:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 22:1 Error: Unexpected tab character. no-tabs 22:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 23:1 Error: Unexpected tab character. no-tabs 23:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 25:1 Error: Unexpected tab character. no-tabs 25:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 26:1 Error: Unexpected tab character. no-tabs 26:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 27:1 Error: Unexpected tab character. no-tabs 27:1 Error: Expected indentation of 6 spaces but found 3 tabs. indent 27:4 Warning: Unexpected alert. no-alert 28:1 Error: Unexpected tab character. no-tabs 28:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 29:1 Error: Unexpected tab character. no-tabs 29:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 31:1 Error: Unexpected tab character. no-tabs 31:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 32:1 Error: Unexpected tab character. no-tabs 32:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 33:1 Error: Unexpected tab character. no-tabs 33:1 Error: Expected indentation of 4 spaces but found 2 tabs. indent 34:1 Error: Unexpected tab character. no-tabs 34:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 36:1 Error: Unexpected tab character. no-tabs 36:1 Error: Expected indentation of 2 spaces but found 1 tab. indent 37:1 Error: Unexpected tab character. no-tabs 37:3 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 38:1 Error: Unexpected tab character. no-tabs 38:4 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 39:1 Error: Unexpected tab character. no-tabs 39:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 39:20 Error: Unexpected usage of singlequote. jsx-quotes 40:1 Error: Unexpected tab character. no-tabs 40:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 41:1 Error: Unexpected tab character. no-tabs 41:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 42:1 Error: Unexpected tab character. no-tabs 42:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 42:11 Error: Unexpected usage of singlequote. jsx-quotes 43:1 Error: Unexpected tab character. no-tabs 43:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 44:1 Error: Unexpected tab character. no-tabs 44:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 45:1 Error: Unexpected tab character. no-tabs 45:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 46:1 Error: Unexpected tab character. no-tabs 46:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 47:1 Error: Unexpected tab character. no-tabs 48:1 Error: Unexpected tab character. no-tabs 48:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 49:1 Error: Unexpected tab character. no-tabs 49:7 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 50:1 Error: Unexpected tab character. no-tabs 50:8 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 50:29 Error: Unexpected usage of singlequote. jsx-quotes 50:42 Error: Unexpected usage of singlequote. jsx-quotes 50:62 Error: Unexpected usage of singlequote. jsx-quotes 51:1 Error: Unexpected tab character. no-tabs 51:8 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 52:1 Error: Unexpected tab character. no-tabs 53:1 Error: Unexpected tab character. no-tabs 54:1 Error: Unexpected tab character. no-tabs 55:1 Error: Unexpected tab character. no-tabs 56:1 Error: Unexpected tab character. no-tabs 56:4 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 57:1 Error: Unexpected tab character. no-tabs 57:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 57:20 Error: Unexpected usage of singlequote. jsx-quotes 58:1 Error: Unexpected tab character. no-tabs 58:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 59:1 Error: Unexpected tab character. no-tabs 59:5 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent 60:1 Error: Unexpected tab character. no-tabs 60:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 60:11 Error: Unexpected usage of singlequote. jsx-quotes 61:1 Error: Unexpected tab character. no-tabs 61:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 62:1 Error: Unexpected tab character. no-tabs 62:6 Error: Expected indentation of 2 space characters but found 0. react/jsx-indent-props 63:1 Error: Unexpected tab character. no-tabs 63:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 64:1 Error: Unexpected tab character. no-tabs 64:1 Error: Expected indentation of 7 spaces but found 6 tabs. indent 65:1 Error: Unexpected tab character. no-tab .eslintrc, next.config.js 는 제로초님의 깃헙과 동일하게 했습니다..eslintrc{ "parser": "@babel/eslint-parser", "parserOptions": { "ecmaVersion": 2020, "sourceType": "module", "ecmaFeatures": { "jsx": true }, "babelOptions": { "presets": ["next/babel"] }, "requireConfigFile": false }, "env": { "browser": true, "node": true, "es6": true }, "extends": ["airbnb"], "plugins": ["import", "react-hooks", "jsx-a11y"], "rules": { "jsx-a11y/label-has-associated-control": "off", "jsx-a11y/anchor-is-valid": "off", "no-console": "off", "no-underscore-dangle": "off", "react/forbid-prop-types": "off", "react/jsx-filename-extension": "off", "react/jsx-one-expression-per-line": "off", "react/jsx-props-no-spreading": "off", "object-curly-newline": "off", "linebreak-style": "off", "no-param-reassign": "off", "max-len": "off", "react/react-in-jsx-scope": "off" } } next.config.jsconst withBundleAnalyzer = require("@next/bundle-analyzer")({ enabled: process.env.ANALYZE === "true", }); module.exports = withBundleAnalyzer({ images: { domains: ["react-nodebird.s3.ap-northeast-2.amazonaws.com", "react-nodebird-s3.s3.amazonaws.com"], }, compress: true, compiler: { styledComponents: { ssr: true, displayName: true, }, }, webpack(config, { webpack }) { const prod = process.env.NODE_ENV === "production"; return { ...config, mode: prod ? "production" : "development", devtool: prod ? "hidden-source-map" : "inline-source-map", plugins: [...config.plugins], }; }, }); /package.json{ "name": "react-nodebird", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "next dev", "build": "cross-env ANALYZE=true NODE_ENV=production next build", "start": "cross-env NODE_ENV=production next start -p 80" }, "author": "", "license": "MIT", "dependencies": { "@ant-design/icons": "^5.3.6", "@next/bundle-analyzer": "^14.2.3", "@reduxjs/toolkit": "^2.2.3", "antd": "^5.8.3", "axios": "^1.6.8", "babel-plugin-styled-components": "^2.1.4", "cross-env": "^7.0.3", "dayjs": "^1.11.11", "lodash": "^4.17.21", "next": "^14.2.3", "next-redux-wrapper": "^8.1.0", "pm2": "^5.3.1", "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.51.3", "react-redux": "^9.1.1", "react-slick": "^0.30.2", "redux": "^5.0.1", "redux-saga": "^1.3.0", "shortid": "^2.2.16", "styled-components": "^6.1.8", "swr": "^2.2.5" }, "devDependencies": { "@babel/eslint-parser": "^7.24.5", "@faker-js/faker": "^8.4.1", "babel-eslint": "^10.1.0", "eslint": "^8.57.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.2" } } 깃헙 : https://github.com/dydcodydco/react-nodebird
-
해결됨Next + React Query로 SNS 서비스 만들기
next-auth로 다시 한번 질문을 올립니다...
공지의 올려주신대로 auth.ts 를 수정하였으며 loginModal 의 redirect:trueexport const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ pages: { signIn: "/i/flow/login", newUser: "/i/flow/signup", }, callbacks: { // async signIn() // async authorized({ auth }) { // if (!auth) { // // 쿠키가 없으면 로그인 페이지로 돌리기 // return NextResponse.redirect("http://localhost:3000/i/flow/login"); // } // return true; // }, }, providers: [ CredentialsProvider({ async authorize(credentials) { const authResponse = await fetch( `${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, // NEXT_PUBLIC_BASE_URL=http://localhost:9090 { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.username, password: credentials.password, }), } ); // 여기 주목!!! 서버에서 에러가 발생할 때 그 에러 내용이 서버에 담겨 있을 겁니다. console.log(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); // id, name, image, email만 허용 return { id: user.id, name: user.nickname, image: user.image, }; }, }), ], }); 아래와 같은 오류가 계속 해서 발생하고 있습니다. TypeError: next_dist_server_web_exports_next_request__WEBPACK_IMPORTED_MODULE_0__ is not a constructor pakage.json 의 버젼은 아래와 같이 사용하고 있고요 "@auth/core": "^0.27.0", "next-auth": "^5.0.0-beta.16",혹시 이 부분의 같은 에러가 나오신 분들 중 해결 하신 분들이 있을까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
서버 실행하고 브라우저로 들어갔을때 404에러
안녕하세요 제로초님서버 실행하고 브라우저로 들어갔을때 404에러가 나오는건정상적인 실행결과가 아닌건가요?제대로 작동하고 있는것 같은데... 저랑 같은 상태로 보이시는 분의 질문이 있는걸 보고 혹시나해서 여쭤봅니다.https://www.inflearn.com/questions/685249/%EC%84%9C%EB%B2%84-%EC%8B%A4%ED%96%89%EC%8B%9C-404%EC%97%90%EB%9F%AC-%EA%B4%80%EB%A0%A8%ED%95%B4%EC%84%9C-%EC%A7%88%EB%AC%B8%EB%93%9C%EB%A6%AC%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
final 과제 코드 질문입니다.
제가 한 final 과제 코드와 정답 코드를 비교해보고 싶은데 final 정답 코드가 있을까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션 7 GraphQL 관련 질문 드립니다
안녕하세요섹션 04-05-graphql-mutation-product 따라하고 있는데 도중에 저런 에러 메세지가 떴습니다.디버깅 하려고 해도 Network 부분에 message 부분이 안 뜨네요ㅠ 검색해보니 쿠키 및 인터넷 기록 삭제해보라고 나오는데..삭제해도 해결이 안 되고요ㅠㅠ 어떻게 해야 해결될까요?도움 부탁드립니다
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
css 서버사이드 랜더링이 적용되지 않아서 문의 드립니다.
https://www.inflearn.com/course/lecture?courseSlug=%EB%85%B8%EB%93%9C%EB%B2%84%EB%93%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%A6%AC%EB%89%B4%EC%96%BC&unitId=49018&category=questionDetail&tab=community&q=1075492안녕하세요 제로초님!위의 질문 답변을 보고 css 서버사이드 랜더링을 하기위해서 이것저것 해보았는데 적용이 안되서 문의 드립니다..babelrc 작성next.config.js에서도 옵션으로 가능하다고해서 수정_document.js 수정빌드 하고 npm start하고 테스트위 링크의 답변 참고해서 @ant-design/cssinjs 적용해봄 그럼에도 적용안되더라구요 ㅠpages/_docuemnts.js (이 전에는 제로초님깃헙의 것을 썼었습니다. 안돼서 @ant-design/cssinjs 적용한 버전입니다.import React from "react"; import Document, { Html, Head, Main, NextScript } from "next/document"; import { createCache, extractStyle, StyleProvider } from "@ant-design/cssinjs"; import { ServerStyleSheet } from "styled-components"; export default class MyDocument extends Document { static async getInitialProps(ctx) { const cache = createCache(); const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => ( <StyleProvider cache={cache}> <App {...props} /> </StyleProvider> ), }); const initialProps = await Document.getInitialProps(ctx); const style = extractStyle(cache, true); return { ...initialProps, styles: ( <> {initialProps.styles} <style dangerouslySetInnerHTML={{ __html: style }} /> </> ), }; } catch (error) { console.error(error); } finally { sheet.seal(); } } render() { return ( <Html> <Head /> <body> <Main /> <NextScript /> </body> </Html> ); } } next.config.jsconst withBundleAnalyzer = require("@next/bundle-analyzer")({ enabled: process.env.ANALYZE === "true", }); module.exports = withBundleAnalyzer({ images: { domains: ["react-nodebird.s3.ap-northeast-2.amazonaws.com", "react-nodebird-s3.s3.amazonaws.com"], }, compress: true, compiler: { styledComponents: { ssr: true, displayName: true, }, }, webpack(config, { webpack }) { const prod = process.env.NODE_ENV === "production"; return { ...config, mode: prod ? "production" : "development", devtool: prod ? "hidden-source-map" : "inline-source-map", plugins: [...config.plugins], }; }, }); .eslintrc{ "parser": "@babel/eslint-parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module", "ecmaFeatures": { "jsx": true }, "requireConfigFile": false, "babelOptions": { "presets": ["next/babel"] } }, "env": { "browser": true, "node": true, "es6": true }, "extends": [ "airbnb", "next/babel" ], "plugins": ["import", "react-hooks", "jsx-a11y"], "rules": { "react/react-in-jsx-scope": "off", "jsx-a11y/label-has-associated-control": "off", "jsx-a11y/anchor-is-valid": "off", "no-console": "off", "no-underscore-dangle": "off", "react/forbid-prop-types": "off", "react/jsx-filename-extension": "off", "react/jsx-one-expression-per-line": "off", "react/jsx-props-no-spreading": "off", "object-curly-newline": "off", "linebreak-style": "off", "no-param-reassign": "off", "max-len": "off" } } /.babelrc{ "presets": ["next/babel"], "plugins": [ [ "styled-components", { "ssr": true, "displayName": true } ] ] } https://github.com/dydcodydco/react-nodebird혹시나해서 깃헙 주소도 남깁니다.마지막으로 하나 더 궁금한게 있습니다.이 강의를 내껄로 만들고, 다음강의 슬랙까지 강의보고 하면중고신입으로 개발자 이직할 수 있을지도 궁금합니다.좋은 강의 정말 감사합니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
팔로워 3명씩 불러오고 데이터 합쳐주는걸로 바꾸고 서버요청을 무한으로하고있습니다.
안녕하세요 제로초님.강의중에 말씀해주셨건걸 참고해서팔로워, 팔로잉을 3명 호출하고, 이후에 다음3명씩 호출하고 불러온 데이터를 합쳐서 리스트를 만드는식으로 바꿔봤습니다.그런데 이슈가 한번 불러오기, 더보기 다 작동하는데 서버 요청을 무한으로 하고 있습니다.어떤 부분을 수정해야할지 봐주실 수 있을까요?limit은 3으로 고정, page를 조절해서 다음 3명씩/pages/profile.jsimport Head from "next/head"; import { useDispatch, useSelector } from "react-redux"; import { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/router"; import axios from "axios"; import useSWR from "swr"; import { loadFollowersRequestAction, loadFollowingsRequestAction, loadMyInfo } from "../reducers/user"; import AppLayout from "../components/AppLayout"; import NicknameEditForm from "../components/NicknameEditForm"; import FollowList from "../components/FollowList"; import wrapper from "../store/configurStore"; const fetcher = (url) => axios.get(url, { widthCredentials: true }).then((result) => { console.log("fetcher----------------------"); return result.data; }); const Profile = () => { const router = useRouter(); const dispatch = useDispatch(); const { me } = useSelector((state) => state.user); const [followersLimit, setFollowersLimit] = useState(1); const [followingsimit, setFollowingsLimit] = useState(1); const [followers, setFollowers] = useState([]); const [followings, setFollowings] = useState([]); const { data: followersData, error: followerError, isLoading: followerLoading, } = useSWR(`http://localhost:3065/user/followers?page=${followersLimit}`, fetcher, { onSuccess: (data) => { setFollowers((prev) => [...prev, ...data]); }, }); const { data: followingsData, error: followingError, isLoading: followingLoading, } = useSWR(`http://localhost:3065/user/followings?page=${followingsimit}`, fetcher, { onSuccess: (data) => { setFollowings((prev) => [...prev, ...data]); }, }); useEffect(() => { if (!(me && me.id)) { router.push("/"); } }, [me && me.id]); const loadMoreFollowings = useCallback(() => { setFollowingsLimit((prev) => prev + 1); }, []); const loadMoreFolloweers = useCallback(() => { setFollowersLimit((prev) => prev + 1); }, []); if (!me) { return <div>내정보 로딩중...</div>; } if (followerError || followingError) { console.error(followerError || followingError); return <div>팔로잉/팔로워 로딩 중 에러 발생...</div>; } return ( <> <Head> <title>내 프로필 | NodeBird</title> </Head> <AppLayout> <NicknameEditForm /> <FollowList header='팔로워' data={followers} onClickMore={loadMoreFolloweers} loading={followerLoading} /> <FollowList header='팔로잉' data={followings} onClickMore={loadMoreFollowings} loading={followingLoading} /> </AppLayout> </> ); }; export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => { console.log(req.headers); const cookie = req ? req.headers.cookie : ""; axios.defaults.headers.Cookie = ""; if (req && cookie) { axios.defaults.headers.Cookie = cookie; } await store.dispatch(loadMyInfo()); }); export default Profile; /routes/userl.js// GET /user/followers 팔로워즈 불러오기 router.get("/followers", isLoggedIn, async (req, res, next) => { try { // 나를 먼저 찾고 const user = await User.findOne({ where: { id: req.user.id }, }); // 내 팔로워즈 get 하기 const limit = parseInt(req.query.limit, 10) || 3; // 기본값 3 const page = parseInt(req.query.page, 10) || 1; // 기본값 1 const offset = (page - 1) * limit; const followers = await user.getFollowers({ limit, offset }); res.status(200).json(followers); } catch (error) { console.error(error); next(error); } }); // GET /user/followings 팔로잉즈 불러오기 // 미들웨어... (req, res, next) 이 콜백함수도 미들웨어 router.get("/followings", isLoggedIn, async (req, res, next) => { try { const user = await User.findOne({ where: { id: req.user.id }, }); const limit = parseInt(req.query.limit, 10) || 3; // 기본값 3 const page = parseInt(req.query.page, 10) || 1; // 기본값 1 const offset = (page - 1) * limit; const followings = await user.getFollowings({ limit, offset }); res.status(200).json(followings); } catch (error) { console.error(error); next(error); } });
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
해시태그 검색에서 throttle에 관해 질문있습니다.
해시태그 검색에서 throttle에 관해 질문있습니다.해시태그 검색을 하게 되면 throttle때문에 5초 이후에 검색이 되고 있습니다.스크롤할 때에는 유용하지만 하나를 클릭하고, 5초 이내에 클릭하게되면 url은 바뀌지만 게시글은 바뀌지 않고 ux에 좋지않아보입니다. const loadHashtagPostsThrottle = async (payload) => { const queryStr = setQuerystring(payload); const url = `/hashtag/${encodeURIComponent(payload.tag)}${queryStr ? "?" + queryStr : ""}`; const response = await axios.get(url); return response; }; export const loadHashtagPosts = createAsyncThunk("post/loadHashtagPosts", _.throttle(loadHashtagPostsThrottle, 5000)); 특저 유저의 게시글을 검색할때도 비슷한 현상이 나올거같은데 이럴땐 어떻게 하면 ux를 좋게 할 수 있을지 궁금합니다.
-
미해결Next + React Query로 SNS 서비스 만들기
제로초님 에러를 해결 하다가 전달 드립니다 ㅠㅠ
react-query를 사용 하고 있는 그중 useQuery를 사용 하고 있습니다 네트워크 탭상에서는 한번만 호출 햇는데 console에서는 회색으로 아래와 같이 두번 호출 한것 처럼 나오는데 이건 어떻게 못막을까요?!조건을 걸어서 확인을 해봤지만 계속 해서 나오더라구여 ㅠㅠ두번의 호출인지 소켓을 요청 했을때 두번을 요청 하더라구여 ㅜㅜ
-
해결됨기초부터 배우는 Next YTMusic 클론 코딩 (with next.js 14, UI 마스터)
8.2에서 보이는 site안에 page파일과 7.6에서 보이는 page파일의 코드가 다른거 같습니다.
8.2에서 보이는 site안에 page파일과 7.6에서 보이는 page파일의 코드가 다른거 같습니다.깃허브에는 7.7 챕터가 따로 있던데... 혹시 그 브랜치에 site안의 page파일을 그대로 사용하면 될까요??
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
[20-03-search-keyword] 에서 질문 있습니다.
다른 코드는 다 처리되고 화면에 반영되는데,노란 부분만 그냥 건너뛰어져요.강의 영상 코드와 여러번 비교하며 그대로 타이핑 했는데요 ㅠ아에 처리도 안되고 그냥 건너뛰어져요 ㅠ