inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

172만명의 커뮤니티!! 함께 토론해봐요.

포트폴리오 SECTION8 댓글 수정 기능 누락

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

여기서 reference Code를 다운 받아 제가 작성한 코드와 비교해보려고 하는데, 댓글 수정 기능은 구현이 되어 있지 않다는 것을 알게 되었습니다. 일부러 댓글 수정 기능은 빼놓은 건가요?

  • react
  • node.js
  • seo
  • graphql
  • next.js
박혜주 댓글 1 좋아요 0 조회수 475

context.req 존재 여부를 2번이나 체크하는 이유?

해결됨

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요 제로초님. const cookie = context.req ? context.req.headers.cookie : ''; axios.defaults.headers.Cookie = ''; if (context.req && cookie) { axios.defaults.headers.Cookie = cookie; } 여기에서 context.req 존재 여부를 2번이나 체크를 하고 있는데요. 그 이유는 cookie 변수 안에 이전의 사용자의 sid가 들어가 있을 것을 (현재의 사용자를 위해) 방지 하기 위함 인가요? 아니면 다른 이유가 있나요? 감사합니다.

  • react
  • redux
  • node.js
  • express
  • next.js
신영 유 댓글 1 좋아요 0 조회수 378

configureStore.js에서 createStore 밑줄 현상으로 인해 빌드 불가

해결됨

[리뉴얼] React로 NodeBird SNS 만들기

[제로초 강좌 질문 필독 사항입니다] 질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다. 도움이 되는 질문을 하는 방법을 알려드립니다. https://www.youtube.com/watch?v=PUKOWrOuC0c 0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다. 1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다. 2. 3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요. import { applyMiddleware, compose, createStore } from "redux"; const store = createStore(reducer, enhancer); 공지사항에서는 결론적으로는 createStore 그대로 쓰셔도 됩니다. 아무 문제 없다고 나와있는데 저는 에러가 떠지면서 안됩니다 ㅠㅠ. 툴킷으로 바꿔야하나요? 바꾸게 되면 진도부분하고 헷갈리지 않을까 걱정이 되긴 하네요

  • react
  • redux
  • node.js
  • express
  • next.js
장산 댓글 1 좋아요 1 조회수 551

테스트 안됨

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

안녕하세요! 테스트 강좌 들으면서 다 똑같이 한것같은데 이런 오류가 뜨네요. __test __ 파일 따로 뺏고 config파일 생성했고 package.json 파일 수정했는데 왜 오류가 나는지 모르겠습니다.ㅜ

  • react
  • node.js
  • seo
  • graphql
  • next.js
ju han 댓글 1 좋아요 0 조회수 379

왜/어떻게 nextjs를 사용하면 백엔드를 사용할 필요가 없나요?

미해결

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요 제로초님. NextJS에 대해 자세히 공부하고 싶은데 공부할 설명자료가 구글에 빈약한 거 같아 실무경험이 있는 제로초님께 쉬운 답변을 얻고 싶습니다. 왜 nextjs를 사용하면 백엔드를 사용할 필요가 없는지 구글링을 해봤고 대충 비슷한 답변을 얻은 거 같긴 한데 아직도 좀 잘 모르겠는 부분이 있습니다. 아래는 제가 찾은 답변을 구글 번역한 것입니다: 그러나 SPA(단일 페이지 애플리케이션)의 등장으로 프런트엔드와 백엔드의 구분이 모호해졌습니다. SPA에서 전체 애플리케이션은 사용자의 브라우저에 로드되고 백엔드는 Node.js와 같은 서버 측 프레임워크에서 처리됩니다. Next.js는 한 단계 더 나아가 백엔드 프레임워크의 필요성을 제거합니다. 이를 통해 완전히 서버 렌더링되는 React 애플리케이션을 만들 수 있습니다. 이것은 사용자의 브라우저가 JavaScript 파일, CSS 파일 및 이미지와 같은 필요한 모든 자산을 포함하여 완전한 HTML 페이지를 다운로드한다는 것을 의미합니다. 또한 React 구성 요소에 대한 지원 기능이 내장되어 있으므로 라우팅, 상태 관리 및 기타 일반적인 프런트엔드 문제에 대해 걱정할 필요 없이 정교한 사용자 인터페이스를 만들 수 있습니다. -> 그래서 "어떻게" 백엔드 프레임워크가 필요하지 않다는 건지 아직도 이해가 안 됩니다 ㅠㅠ 예시를 들어 설명해 주시면 정말 감사하겠습니다!! 예를들어, 제가 궁금한 점은, DB에서 node를 거치지 않고 Nextjs에서 바로 data를 가져올 수 있는지? 등등 원문: However, with the rise of single-page applications (SPAs), the distinction between frontend and backend has become less clear. In a SPA, the entire application is loaded in the user’s browser, and the backend is handled by a server-side framework like Node.js. Next.js eliminates the need for a backend framework by taking it one step further. It allows you to create React applications that are completely server-rendered. This means that the user’s browser will download a complete HTML page, including all the necessary assets like JavaScript files, CSS files, and images. It also ships with built-in support for React components, so you can create sophisticated user interfaces without having to worry about routing, state management, and other common frontend concerns. 참고: https://matcha.fyi/nextjs-intro/#:~:text=js.-,Next.,%2C%20CSS%20files%2C%20and%20images .

  • react
  • redux
  • node.js
  • express
  • next.js
신영 유 댓글 2 좋아요 0 조회수 13685

Google api 매장 데이터

해결됨

Next.js 시작하기(feat. 지도 서비스 개발)

안녕하세요 현재 네이버맵 대신 구글맵 api를 사용중인데 아무리 찾아봐도 선생님 stores.json 값처럼 json데이터를 찾을수가없네요 ㅠㅠ 일단 현재 그냥 stores.json 선생님이 가지고있는데이터 사용중이긴한데 다른질문 답변보니 크롤링하셔서 데이터를 만드신거같은데 혹시 저의경우에는 방법이있을까요??

  • seo
  • next.js
  • vercel
  • csr
  • ssg
  • ssr
YeongHeon KIM 댓글 1 좋아요 1 조회수 903

styled-component ssr

미해결

[리뉴얼] React로 NodeBird SNS 만들기

스타일드 컴포넌트 ssr을 설정을 했는데도 자꾸 css가 깨지는데 혹시 어느 부분을 살펴보면 될까요 바벨과 document부분 모두 설정했습니다 강좌와는 다르게 타입스크립트로 진행했습니다

  • react
  • redux
  • node.js
  • express
  • next.js
bs44108 댓글 1 좋아요 0 조회수 491

백엔드를 만드려면 backend course부분 수강해야 하나요?

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

백엔드를 만드는 부분은 backend course를 들어야 가능한가요? 중고마켓 부분 포트폴리오를 만드려고 하는데 playground 부분을 직접 설계하고 싶다는 생각이 들었습니다. 프론트 강의에 그 부분이 포함되어 있나요? 저는 간단한 중고마켓을 만들고 싶은데 백엔드 분량이 너무 많아서 프론트 강의에 백엔드 부분 있길래 백엔드 강의(백엔드 부트캠프)는 나중에 들을려고 결제를 미뤘습니다. 일단 포트폴리오 만드는데에는 프론트 강의만으로 충분한가요? 저만의 웹페이지를 만들려면 강의 api보다는 직접 api를 만들어서 하는게 좋다고 생각해서 강의를 구매했습니다.

  • react
  • node.js
  • seo
  • graphql
  • next.js
rjsdn wkd 댓글 1 좋아요 0 조회수 280

SSR이 아닐때 = CSR일때 쿠키 withCredentials 안 해줘도 되나요?

해결됨

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요 제로초님. 2:27 쯤에서 질문이 생겼습니다. 그러면 SSR이 아닐때 = CSR일때에는 front에서 쿠키 withCredentials 안 해주고, back에서만 credentials: true 해줘도 문제가 없는 건가요?

  • react
  • redux
  • node.js
  • express
  • next.js
신영 유 댓글 2 좋아요 0 조회수 382

.next 파일 관련

미해결

[리뉴얼] React로 NodeBird SNS 만들기

aws ec2 인스턴스 하나에 프론트와 백을 동시에 실행시키려고 합니다 다만 프리티어 메모리 부족으로 npm run build를 로컬에서 빌드한 이후 .next 파일을 깃허브에 푸쉬해서 인스턴스에서 Pull받은 다음 npm start를 하려고 하는데 문제가 .next파일 용량이 커서 깃허브에 업로드가 안됩니다 lfs라는 방식으로 해결을 했지만 푸쉬를 할때마다 깃허브 무료 용량이 다 차는 바람에 쓰지 못하게 될것 같습니다 혹시 다른 방법이 있을까요? 그리고 프론트 서버에서 npm start를 했을때 next/prerender-manifest.json: unexpected token v in json at position 0 이런 에러가 나오는데 로컬에서 빌드하고 npm start했을때는 나오지 않던 에러여서 당황스럽네요 구글링도 해봤는데 해결하지 못했습니다 ㅜㅜ 혹시 방법이 있을까요?

  • react
  • redux
  • node.js
  • express
  • next.js
bs44108 댓글 2 좋아요 0 조회수 1129

background white 문제

해결됨

따라하며 배우는 리액트 A-Z[19버전 반영]

안녕하세요. 선생님. 강의에서 보이는 페이지랑 다르게 제껀 App 컴포넌트의 div 색깔이 흰색이더라구요. 혹시나 싶어 강의 소스 코드를 전부 확인해봐도 검정색으로 App 컴포넌트의 div background 컬러를 지정해주는 부분이 없는 것 같은데 어떤 차이가 있길래 제껀 흰색 배경이고 선생님껀 검정색 배경인지 알 수 있을까요? 소스코드 첨부합니다. https://github.com/edd1e-dev/react-netflix-clone 요약) 배경이 흰색인데 검정색 부분으로 바꿔주는 부분을 못찾겠습니다.

  • react
  • redux
  • tdd
  • typescript
  • next.js
강토토 댓글 1 좋아요 0 조회수 813

15강 질문 드립니다!

미해결

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

15강 람다식 질문 드립니다! 선생님 안녕하세요! 15강에서 작성해주신 람다식이 있는데 람다식을 사용하지 않은 코드도 댓글로 알려주실 수 있으실까요~! 자바 공부를 시작한 지 얼마 되지 않아서 혼자 해보려 해도 잘 안되네요..! 부탁 드리겠습니다!! 감사합니다!

  • java
  • spring
  • aws
  • mysql
  • spring-boot
  • jpa
김한솔 댓글 1 좋아요 2 조회수 541

이미지업로드 graphql

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

안녕하세요! 이미지 업로드부분 강의 듣고있는데 class 폴더에서 진행하고있고 진행하는 서버에는 파일업로드 mutation이 없어요 포폴 서버에는 있는데 강의는 그냥 눈으로 보기만하고 포폴만들때 실습을 해야되는건가요? 검색기능 강의도 마찬가지인것 같아요,,, 그뒤 강의는 아직 안들어서 모르겠어요,,, const UPLOAD_FILE = gql` mutation uploadFile($file: Upload!) { uploadFile(file: $file) { url } } `; 이부분입니다,,,ㅠ

  • react
  • node.js
  • seo
  • graphql
  • next.js
댓글 1 좋아요 0 조회수 478

prefetch 디바운싱

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

강의 끝부분에 퀴즈로 디바운싱 퀴즈가 나와서 코드를 짰긴했는데,, 레퍼런스가 없어서 제가 짠 코드가 맞는지 알고싶습니다..! 아래는 강의 후 추가한 코드입니다. const getDebounce = _.debounce(async (boardId) => { await client.query({ query: FETCH_BOARD, variables: { boardId }, }); }, 500); const prefetchBoard = (boardId: string) => async () => { // await getDebounce(boardId); }; 개발자 도구에서 네트워크 확인결과 0.5초 뒤에 패치를 하는걸로 확인이 되긴 합니다만..제가 올바르게 짠건가요?

  • react
  • node.js
  • seo
  • graphql
  • next.js
ju han 댓글 1 좋아요 0 조회수 252

이미지 업로드 시 data가 보내지지 않습니다..ㅠㅠ

미해결

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요. 강사님! 강의를 들으며 똑같이 작성했고 혹시 모를 오타가 있는지도 확인하면서 강사님 깃허브도 참조해보았는데 원인을 찾지 못하겠어서 문의드립니다. ㅠ ㅠ 이미지 업로드를 하면 아래와 같이 오류가 뜨고 redux dev tools 로 확인해 보았을 때 UPLOAD_IMAGES_REQUEST 만 처리되고 SUCCESS 로 넘어가지가 않아요. 리퀘스트 되어 있는 데이터를 보면 빈 값인 것을 보니 데이터가 넘어가지 않는 것 같은데 도무지 원인을 모르겠습니다. 업로드를 하면 에러가 나면서 서버연결도 끊깁니다. ㅜㅜ 제 코드에 뭐가 문제가 있는 건가요..?ㅠㅠ 확인 후 문제를 알려주시면 너무 감사할 것 같습니다..ㅠㅠㅠ [redux] import produce from "immer"; export const initialState = { mainPosts: [], // 이미지 업로드할 때 이미지의 경로들이 저장됨 imagePaths: [], uploadImagesLoading: false, uploadImagesDone: false, uploadImagesError: null, } export const UPLOAD_IMAGES_REQUEST = "UPLOAD_IMAGES_REQUEST"; export const UPLOAD_IMAGES_SUCCESS = "UPLOAD_IMAGES_SUCCESS"; export const UPLOAD_IMAGES_FAILURE = "UPLOAD_IMAGES_FAILURE"; const reducer = (state = initialState, action) => { return produce(state, (draft) => { switch (action.type) { case UPLOAD_IMAGES_REQUEST: draft.uploadImagesLoading = true; draft.uploadImagesDone = false; draft.uploadImagesError = null; break; case UPLOAD_IMAGES_SUCCESS: draft.imagePaths = action.data; draft.uploadImagesLoading = false; draft.uploadImagesDone = true; break; case UPLOAD_IMAGES_FAILURE: draft.uploadImagesLoading = false; draft.uploadImagesError = action.error; break; default: break; } }); }; export default reducer; [saga] import axios from "axios"; import { all, fork, put, takeLatest, throttle, call, } from "redux-saga/effects"; import { UPLOAD_IMAGES_FAILURE, UPLOAD_IMAGES_REQUEST, UPLOAD_IMAGES_SUCCESS, } from "../reducers/post"; function uploadImagesAPI(data) { return axios.post("/post/images", data); } function* uploadImages(action) { try { const result = yield call(uploadImagesAPI, action.data); yield put({ type: UPLOAD_IMAGES_SUCCESS, data: result.data, }); } catch (err) { console.error(err); yield put({ type: UPLOAD_IMAGES_FAILURE, error: err.response.data, }); } } function* watchUploadImages() { yield takeLatest(UPLOAD_IMAGES_REQUEST, uploadImages); } export default function* postSaga() { yield all([ fork(watchUploadImages), ]); } [components] import React, { useCallback, useEffect, useRef } from "react"; import { useSelector, useDispatch } from "react-redux"; import { Form, Input, Button } from "antd"; import { UPLOAD_IMAGES_REQUEST, REMOVE_IMAGE, ADD_POST_REQUEST, } from "../reducers/post"; import useInput from "../hooks/useInput"; const PostForm = () => { const dispatch = useDispatch(); const { imagePaths, addPostDone } = useSelector((state) => state.post); const [text, onChangeText, setText] = useInput(""); const imageInput = useRef(); useEffect(() => { if (addPostDone) { setText(""); } }, [addPostDone]); const onSubmit = useCallback(() => { if (!text || !text.trim()) { return alert("게시글을 작성하세요."); } const formData = new FormData(); imagePaths.forEach((p) => { formData.append("image", p); }); formData.append("content", text); return dispatch({ type: ADD_POST_REQUEST, data: formData, }); }, [text, imagePaths]); const onClickImageUpload = useCallback(() => { imageInput.current.click(); }, [imageInput.current]); const onChangeImages = useCallback((e) => { console.log("images", e.target.files); const imageFormData = new FormData(); [].forEach.call(e.target.files, (f) => { imageFormData.append("image", f); }); dispatch({ type: UPLOAD_IMAGES_REQUEST, data: imageFormData, }); }, []); const onRemoveImage = useCallback( (index) => () => { dispatch({ type: REMOVE_IMAGE, data: index, }); }, [] ); return ( <Form style={{ margin: "10px 0 20px" }} encType="multipart/form-data" onFinish={onSubmit} > <Input.TextArea value={text} onChange={onChangeText} maxLength={140} placeholder="어떤 신기한 일이 있었나요?" /> <div> <input type="file" name="image" multiple hidden ref={imageInput} onChange={onChangeImages} /> <Button onClick={onClickImageUpload}>이미지 업로드</Button> <Button type="primary" style={{ float: "right" }} htmlType="submit"> 짹짹 </Button> </div> <div> {imagePaths?.map((v, i) => ( <div key={v} style={{ display: "inline-block" }}> <img src={`http://localhost:3065/${v}`} alt={v} style={{ width: "200px" }} /> <div> <Button onClick={onRemoveImage(i)}>제거</Button> </div> </div> ))} </div> </Form> ); }; export default PostForm; [back - routes/post.js] const express = require("express"); const multer = require("multer"); const path = require("path"); const fs = require("fs"); const { Post, Image, Comment, User } = require("../models"); const { isLoggedIn } = require("./middlewares"); const router = express.Router(); try { fs.accessSync("uploads"); } catch (error) { console.log("uploads 폴더가 없으므로 생성합니다."); fs.mkdirSync("uploads"); } const upload = multer({ storage: multer.diskStorage({ destination(req, file, done) { done(null, "uploads"); }, filename(req, file, done) { // amanda.png const ext = path.extname(file.originalname); // 확장자 추출(.png) const basename = path.basename(file.originalname, ext); // amanda done(null, basename + "_" + new Data().getTiem() + ext); // amanda15653484.png }, }), limits: { fileSize: 20 * 1024 * 1024 }, // 20MB }); router.post( "/images", isLoggedIn, upload.array("image"), // single , array , none async (req, res, next) => { // POST /post/images console.log(req.files); res.json(req.files.map((v) => v.filename)); } ); router.post("/", isLoggedIn, upload.none(), async (req, res) => { // POST /post try { const post = await Post.create({ content: req.body.content, UserId: req.user.id, }); if (req.body.image) { if (Array.isArray(req.body.image)) { // 이미지를 여러 개 올리면 image: [제로초.png, 부기초.png] const images = await Promise.all( req.body.image.map((image) => Image.create({ src: image })) ); await post.addImages(images); } else { // 이미지를 하나만 올리면 image: 제로초.png const image = await Image.create({ src: req.body.image }); await post.addImages(image); } } const fullPost = await Post.findOne({ where: { id: post.id }, include: [ { model: Image, }, { model: Comment, include: [ { model: User, // 댓글 작성자 attributes: ["id", "nickname"], }, ], }, { model: User, // 게시글 작성자 attributes: ["id", "nickname"], }, { model: User, // 좋아요 누른 사람 as: "Likers", attributes: ["id"], }, ], }); res.status(201).json(fullPost); } catch (error) { console.error(error); next(error); } }); module.exports = router;

  • react
  • redux
  • node.js
  • express
  • next.js
DDU 댓글 1 좋아요 0 조회수 359

post 에서 작성 후 mainPosts.map 에서 key={post.id} 가 undefined 로 나옵니다.

미해결

[리뉴얼] React로 NodeBird SNS 만들기

에러메세지: ADD_POST_SUCCESS 까지 잘 되었고 content 에 id 도 잘 들어가 있는걸로 보입니다. pages/index.js import React, { 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 { LOAD_POSTS_REQUEST } from "../reducers/post"; import { LOAD_USER_REQUEST } from "../reducers/user"; const Home = () => { const me = useSelector((state) => state.user.me); const { mainPosts, hasMorePosts, isLoadingPosts } = useSelector( (state) => state.post ); const dispatch = useDispatch(); useEffect(() => { dispatch({ type: LOAD_USER_REQUEST, }); dispatch({ type: LOAD_POSTS_REQUEST, }); }, []); useEffect(() => { function onScroll() { if ( window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300 ) { if (hasMorePosts && !isLoadingPosts) { dispatch({ type: LOAD_POSTS_REQUEST, }); } } } window.addEventListener("scroll", onScroll); return () => { window.removeEventListener("scroll", onScroll); }; }, []); return ( <AppLayout> {me && <PostForm />} {mainPosts.map((post) => ( <PostCard key={post.id} post={post} /> ))} </AppLayout> ); }; export default Home; reducers/post.js import produce from "immer"; export const initialState = { mainPosts: [], imagePaths: [], hasMorePosts: true, isAddingPost: false, isAddedPost: false, isAddPostErr: null, isRemovingPost: false, isRemovedPost: false, isRemovePostErr: null, isAddingComment: false, isAddedComment: false, isAddCommentErr: null, isRemovingComment: false, isRemovedComment: false, isRemoveCommentErr: null, isLoadingPosts: false, isLoadedPosts: false, isLoadPostsErr: null, }; export const LOAD_POSTS_REQUEST = "LOAD_POSTS_REQUEST"; export const LOAD_POSTS_SUCCESS = "LOAD_POSTS_SUCCESS"; export const LOAD_POSTS_FAILURE = "LOAD_POSTS_FAILURE"; export const ADD_POST_REQUEST = "ADD_POST_REQUEST"; export const ADD_POST_SUCCESS = "ADD_POST_SUCCESS"; export const ADD_POST_FAILURE = "ADD_POST_FAILURE"; export const REMOVE_POST_REQUEST = "REMOVE_POST_REQUEST"; export const REMOVE_POST_SUCCESS = "REMOVE_POST_SUCCESS"; export const REMOVE_POST_FAILURE = "REMOVE_POST_FAILURE"; export const ADD_COMMENT_REQUEST = "ADD_COMMENT_REQUEST"; export const ADD_COMMENT_SUCCESS = "ADD_COMMENT_SUCCESS"; export const ADD_COMMENT_FAILURE = "ADD_COMMENT_FAILURE"; export const addPost = (data) => ({ type: ADD_POST_REQUEST, data, }); const reducer = (state = initialState, action) => { return produce(state, (draft) => { switch (action.type) { case ADD_POST_REQUEST: draft.isAddingPost = true; draft.isAddedPost = false; draft.isAddPostErr = null; break; case ADD_POST_SUCCESS: draft.isAddingPost = false; draft.mainPosts.unshift(action.data); draft.isAddedPost = true; break; case ADD_POST_FAILURE: draft.isAddingPost = false; draft.isAddedPost = false; draft.isAddPostErr = action.error; break; case REMOVE_POST_REQUEST: draft.isRemovingPost = true; draft.isRemovedPost = false; draft.isRemovePostErr = null; break; case REMOVE_POST_SUCCESS: draft.isRemovingPost = false; draft.mainPosts = state.mainPosts.filter((v) => v.id !== action.data); draft.isRemovedPost = true; draft.isRemovePostErr = null; break; case REMOVE_POST_FAILURE: draft.isRemovingPost = false; draft.isRemovedPost = false; draft.isRemovePostErr = action.error; break; case ADD_COMMENT_REQUEST: draft.isAddingComment = true; draft.isAddedComment = false; draft.isAddCommentErr = null; break; case ADD_COMMENT_SUCCESS: draft.isAddingComment = false; const post = draft.mainPosts.find((v) => v.id === action.data.PostId); post.Comments.unshift(action.data); draft.isAddedComment = true; break; case ADD_COMMENT_FAILURE: draft.isAddingComment = false; draft.isAddedComment = false; draft.isAddCommentErr = action.error; break; case LOAD_POSTS_REQUEST: draft.isLoadingPosts = true; draft.isLoadedPosts = false; draft.isLoadPostsErr = null; break; case LOAD_POSTS_SUCCESS: draft.isLoadingPosts = false; draft.mainPosts = draft.mainPosts.concat(action.data); draft.isLoadedPosts = true; break; case LOAD_POSTS_FAILURE: draft.isLoadingPosts = false; draft.isLoadedPosts = false; draft.isLoadPostsErr = action.error; break; default: break; } }); }; export default reducer; sagas/post.js import { delay, all, fork, put, takeLatest, call } from "redux-saga/effects"; import axios from "axios"; import { ADD_POST_REQUEST, ADD_POST_SUCCESS, ADD_POST_FAILURE, ADD_COMMENT_FAILURE, ADD_COMMENT_SUCCESS, ADD_COMMENT_REQUEST, REMOVE_POST_REQUEST, REMOVE_POST_SUCCESS, REMOVE_POST_FAILURE, LOAD_POSTS_REQUEST, LOAD_POSTS_SUCCESS, LOAD_POSTS_FAILURE, } from "../reducers/post"; import { ADD_POST_TO_ME, REMOVE_POST_FROM_ME } from "../reducers/user"; function addPostAPI(data) { return axios.post( "/post", { content: data }, { withCredentials: true, } ); } function* addPost(action) { try { const result = yield call(addPostAPI, action.data); yield put({ type: ADD_POST_SUCCESS, content: result.data }); yield put({ type: ADD_POST_TO_ME, data: result.data.id, }); } catch (err) { console.log(err); yield put({ type: ADD_POST_FAILURE, error: err.response.data, }); } } function removePostAPI(data) { return axios.delete("/post", data); } function* removePost(action) { try { yield delay(1000); yield put({ type: REMOVE_POST_SUCCESS, data: action.data, }); yield put({ type: REMOVE_POST_FROM_ME, data: action.data, }); } catch (err) { yield put({ type: REMOVE_POST_FAILURE, error: err.response.data, }); } } function addCommentAPI(data) { return axios.post(`/post/${data.postId}/comment`, data); //POST /post/1/comment } function* addComment(action) { try { const result = yield call(addCommentAPI, action.data); yield put({ type: ADD_COMMENT_SUCCESS, data: result.data }); } catch (err) { console.log(err); yield put({ type: ADD_COMMENT_FAILURE, error: err, }); } } function loadPostsAPI() { return axios.get(`/posts`); } function* loadPosts(action) { try { const result = yield call(loadPostsAPI, action.data); yield put({ type: LOAD_POSTS_SUCCESS, data: result.data }); } catch (err) { console.log(err); yield put({ type: LOAD_POSTS_FAILURE, error: err.response.data, }); } } function* watchAddPost() { yield takeLatest(ADD_POST_REQUEST, addPost); } function* watchRemovePost() { yield takeLatest(REMOVE_POST_REQUEST, removePost); } function* watchAddComment() { yield takeLatest(ADD_COMMENT_REQUEST, addComment); } function* watchLoadPosts() { yield takeLatest(LOAD_POSTS_REQUEST, loadPosts); } export default function* postSaga() { yield all([ fork(watchAddPost), fork(watchRemovePost), fork(watchAddComment), fork(watchLoadPosts), ]); } routes/posts.js const express = require("express"); const { Post, Image, User, Comment } = require("../models"); const router = express.Router(); router.get("/", async (req, res, next) => { // GET /posts try { const posts = await Post.findAll({ limit: 10, order: [ ["createdAt", "DESC"], [Comment, "createdAt", "DESC"], ], include: [ { model: User, attributes: ["id", "nickname"], }, { model: Image, }, { model: Comment, include: [{ model: User, attributes: ["id", "nickname"] }], }, ], }); res.status(200).json(posts); } catch (err) { console.error(err); next(err); } }); module.exports = router; sql 테이블도 잘 들어가있고, 새로 고침 하면 포스팅은 잘 되어 있습니다.

  • react
  • redux
  • node.js
  • express
  • next.js
Sim Gyuhun 댓글 1 좋아요 0 조회수 461

.next파일

미해결

[리뉴얼] React로 NodeBird SNS 만들기

로컬에서 Next를 빌드해서 aws 인스턴스에서 Npm start를 하려고 하는데 .next파일을 git에 푸쉬했을때 문제가 생기는 부분이 있을까요? 보안이라던지

  • react
  • redux
  • node.js
  • express
  • next.js
bs44108 댓글 1 좋아요 0 조회수 237

프론트서버를 s3로 배포하는 방식은 어떤가요?

해결됨

[리뉴얼] React로 NodeBird SNS 만들기

강좌에서는 ec2 인스턴스 2개로 프론트 백엔드를 유지하는 방식인데 블로그 글들을 찾아보면 프론트서버는 s3로 유지하는 경우가 많더라구요. Get post patch delete 같은 요청에 열려있다는 단점은 있지만 프론트서버같은 정적인 컨텐츠에는 큰 무리가 없고 무엇보다 ec2 2개를 만드는것보다 과금이 없다는건데.. 실제 서비스를 운영할때는 어떤방식으로 하는 편인가요?

  • react
  • redux
  • node.js
  • express
  • next.js
kenny 댓글 1 좋아요 0 조회수 547

[section09] Quiz Ant-design DatePicker library

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

안녕하세요 section09 퀴즈에서 Ant-design Date picker 를 사용하는 과정에서 질문이 생겨 여쭤봅니다. import { DatePicker} from 'antd'; import type { DatePickerProps } from 'antd'; import { useState } from 'react'; export default function AndDesignPage() { const [date, setDate] = useState(''); const [month, setMonth] = useState(''); const onChange: DatePickerProps['onChange'] = (date, dateString) => { console.log(date); setDate(dateString); setMonth(date?.$M + 1);👈👈👈 1️⃣ }; return ( <> <h1>Q2. DatePicker</h1> <span> <DatePicker onChange={onChange} />👈👈👈 2️⃣ </span> {month && ( <> <p>선택날짜 : {date}</p> <p>{month}월을 선택하셨습니다.</p> </> )} </> ); } 전체 코드는 위와 같고 1️⃣,2️⃣번에 빨간 줄이 쳐졌습니다. 1️⃣번은 아래와 같은 메세지가 뜹니다. console.log(date)를 했을 때 아래와 같이 콘솔이 나와서 $M을 활용했는데 작동도 잘 되고 콘솔메세지에도 따로 에러가 뜨지는 않습니다. 2️⃣번은 아래와 같은 문제입니다 에러메세지 전문은 다음과 같습니다. (alias) const DatePicker: PickerComponentClass<PickerProps<Dayjs> & { status?: "" | "warning" | "error" | undefined; hashId?: string | undefined; popupClassName?: string | undefined; rootClassName?: string | undefined; }, unknown> & { WeekPicker: import("./generatePicker/interface").PickerComponentClass<Omit<PickerProps<Dayjs> & { status?: "" | "warning" | "error" | undefined; hashId?: string | undefined; popupClassName?: string | undefined; rootClassName?: string | undefined; }, "picker">, unknown>; MonthPicker: import("./generatePicker/interface").PickerComponentClass<Omit<PickerProps<Dayjs> & { status?: "" | "warning" | "error" | undefined; hashId?: string | undefined; popupClassName?: string | undefined; rootClassName?: string | undefined; }, "picker">, unknown>; YearPicker: import("./generatePicker/interface").PickerComponentClass<Omit<PickerProps<Dayjs> & { status?: "" | "warning" | "error" | undefined; hashId?: string | undefined; popupClassName?: string | undefined; rootClassName?: string | undefined; }, "picker">, unknown>; RangePicker: import("./generatePicker/interface").PickerComponentClass<BaseRangePickerProps<Dayjs> & { dropdownClassName?: string | undefined; popupClassName?: string | undefined; }, unknown>; TimePicker: import("./generatePicker/interface").PickerComponentClass<Omit<Omit<import("rc-picker/lib/Picker").PickerTimeProps<Dayjs>, "locale" | "generateConfig" | "hideHeader" | "components" | "hourStep"> & { locale ... import DatePicker 'DatePicker' cannot be used as a JSX component. Its instance type 'Component<PickerProps<Dayjs> & { status?: "" | "warning" | "error" | undefined; hashId?: string | undefined; popupClassName?: string | undefined; rootClassName?: string | undefined; }, unknown, any> & CommonPickerMethods' is not a valid JSX element. The types returned by 'render()' are incompatible between these types. Type 'React.ReactNode' is not assignable to type 'import("/Users/bible/Bible_Highting/codecamp-frontend-bible/class_quiz/node_modules/@types/react-transition-group/node_modules/@types/react/index").ReactNode'. Type '{}' is not assignable to type 'ReactNode'.ts(2786) 1️⃣,2️⃣번 모두 작동에는 이상이 없으나 빨간줄의 원인과 해결방법을 알고싶어 질문드립니다. 감사합니다!

  • react
  • node.js
  • seo
  • graphql
  • next.js
bearsk711 댓글 1 좋아요 0 조회수 761

aws 포트지정

미해결

[리뉴얼] React로 NodeBird SNS 만들기

노드버드 프로젝트를 하나의 인스턴스에서 프론트와 백 서버 둘다 올리기 위해서 aws 인스턴스 3000번 포트와 3065번 포트를 열어놓으려고 하는데 사용자지정tcp에서 열어놓으면 되는걸까요?

  • react
  • redux
  • node.js
  • express
  • next.js
bs44108 댓글 1 좋아요 0 조회수 385

인기 태그

인프런 TOP Writers

주간 인기글