172만명의 커뮤니티!! 함께 토론해봐요.
해결됨
[리뉴얼] React로 NodeBird SNS 만들기
강의 들은 부분을 툴킷으로 다시 만들어보는중 SSR 적용하는 부분 질문있습니다. 초기 로딩후 로그인은 정상적으로 동작하는데요 새로고침하고 로그인 풀린 화면이 나오고 다시 로그인하면 로그인되지 않습니다. 코드는 다음과 같이 작성했습니다. // toolkit/index.ts import axios from 'axios'; import userSlice, { UserInitialState } from './user'; import postSlice, { PostState } from './post'; import { AnyAction, CombinedState } from '@reduxjs/toolkit'; import { combineReducers } from 'redux'; import { HYDRATE } from 'next-redux-wrapper'; axios.defaults.baseURL = 'http://localhost:3065'; axios.defaults.withCredentials = true; export interface IState { user: UserInitialState; post: PostState; } const rootReducer = ( state: IState, action: AnyAction ): CombinedState<IState> => { switch (action.type) { case HYDRATE: return action.payload; default: { const combinedReducer = combineReducers({ user: userSlice.reducer, post: postSlice.reducer, }); return combinedReducer(state, action); } } }; export default rootReducer; 툴킷에 HYDRATE를 적용하고 // store/configureStore.ts import { AnyAction, Reducer, configureStore } from '@reduxjs/toolkit'; import { createWrapper } from 'next-redux-wrapper'; import rootReducer, { IState } from '../toolkit'; const makeStore = () => configureStore({ reducer: rootReducer as Reducer<IState, AnyAction>, devTools: true, middleware: (getDefaultMiddleware) => getDefaultMiddleware(), }); export default createWrapper<AppStore>(makeStore, { debug: process.env.NODE_ENV !== 'production', }); export type AppStore = ReturnType<typeof makeStore>; export type RootState = ReturnType<typeof rootReducer>; export type AppDispatch = AppStore['dispatch']; 리덕스 래퍼 부분은 저렇게 만들고 //pages/index.tsx export const getServerSideProps: GetServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => { const cookie = req ? req.headers.cookie : ''; axios.defaults.headers.Cookie = ''; if (req && cookie) { axios.defaults.headers.Cookie = cookie; } await store.dispatch(loadPostAction()); await store.dispatch(loadUserAction()); }); export default Home; // toolkit/user.ts export const loadUserAction = createAsyncThunk( 'user/loadUser', async (data) => { const response = await axios.get(`/user/${data}`); return response.data; } ); .addCase(loadUserAction.fulfilled, (draft, action) => { draft.loadUserLoading = false; draft.loadUserDone = true; draft.me = action.payload || null; }) 툴킷쪽은 이런식으로 작성했습니다.
react redux node.js express next.js
ㅇㅅㅇ?
2023-09-21T03:03:38.559Z
댓글 1
좋아요 0
조회수 313
해결됨
자바 ORM 표준 JPA 프로그래밍 - 기본편
안녕하세요. 현재 JPA강의를 통해 회사내 프로젝트중인 직장인 입니다. 실무 중에 강의의 복합키 매핑과는 조금 다른 내용이 있어 며칠을 고민하다 문의 드립니다. 각각 복합키를 가진 두 개의 테이블 이 있습니다. 두 테이블은 code라는 공통 컬럼이있고 다대일관계로 매핑 을 구성하려고 합니다. @EmbeddedId관계 를 이용해 구성하려고 합니다. code 컬럼만 매핑시키는 방법을 찾지 못해 문의 남겨드립니다. 현재 문제의 테이블입니다.(회사프로젝트 테이블이라 자세히 올려드리는 못하는 점 양해 부탁드립니다.) Company Table은 code, biznumber 두 개의 pk로 구성돼 있습니다. Contract Table 역시 code, module 두 개의 pk로 구성돼 있습니다. 저는 두 테이블에서 code라는 컬럼만 갖고 다대일 매핑 을 구현하고 싶습니다. 즉 복합키를 각각 가진 두 개의 테이블에서 각각 하나의 컬럼만을 이용해 다대일 매핑을 구현하고 싶습니다. 제가 에러 내용과 과정을 올리고싶은데 회사코드라 올리면 문제가 생길까 싶어 이렇게 말로 표현드려 죄송합니다.
차재욱
2023-09-21T02:05:50.715Z
댓글 2
좋아요 1
조회수 978
해결됨
현재 Next 13 APP라우팅 방식으로 프로젝트를 하고 있습니다. 프로젝트에서 전역상태관리를 위해서 ContextAPI를 이용하고 Provider를 아래와 같은 방법으로 적용을 시켜줬습니다. (layout.js) return ( <html> <body> <Provider> {children} </Provider> </body> </html> ) (Provider.js) 'use client' //생략 export default function Provider({children}) { return ( <ContextProviber> {children} </ContextProviber> ) } 이렇게 Provider로 감싸주었더니 'use client'를 사용하여 CSR환경에서 작동해야 한다고 하더라구요. 그래서 "use client"까지 적용했는데 이렇게 'use client'로 작성된 component로 감싸면 이 아래오는 모든 코드가 SCR로 적용되는 건가요? 만약 이게 맞다면 SSR의 장점을 전혀 살리지 못하는 것인데 어떻게 해결할 수 있나요?
next next.js next13 상태관리 전역상태관리 redux zustand recoil context ssr
삶은달걀
2023-09-21T01:33:04.241Z
댓글 1
좋아요 0
조회수 2449
미해결
[리뉴얼] React로 NodeBird SNS 만들기
제로쵸 선생님 너무 궁금해서 질문드립니다 ㅜ 흔히 CSR은 SEO 최적화가 어렵다고 하는데 최적화가 어렵지 기본적인 메인 홈페이지는 검색이 되는게 맞죠? 시작이 되는 index.html의 소스의 <head></head> 태그안에 meta 태그 속성 중 네임과 컨텐트, 그리고 타이틀 태그로 인해서, 기본적인 메인 홈페이지는 검색이 되는것 맞나요?
react redux node.js express next.js
오르골
2023-09-20T23:36:54.054Z
댓글 1
좋아요 0
조회수 206
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
동적 라우팅 폴더를 생성해서 강의 따라서 입력했는데 경로에 들어가면 qqq 폴더 관련하여 에러가 뜹니다ㅠ 다르게 입력한건 없는데 왜 이런걸까요?
react node.js seo graphql next.js
쟌
2023-09-20T15:29:42.771Z
댓글 1
좋아요 0
조회수 210
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
섹션 27 라우팅 강의를 따라서 진행하며 useRouter 를 사용해 router.push(/폴더경로) 를 입력하고 버튼 onClick 이벤트에 바인딩 해주었습니다. 각 버튼 클릭시 url 은 정상적으로 이동되는걸로 나오는데, UI 화면은 바뀌지가 않습니다. 콘솔로그를 찍어봐도 클릭 이벤트도 정상작동 되는걸로 나오는데.. 도대체 뭐가 문제일까요ㅠ APP.js 에서 컴포넌트를 바꿔봤을 때도 각 버튼 별 이동 페이지들이 문제없이 뜨는걸 확인했습니다. url 이동시 화면만 새로고침되지 않는 것 같아요.. 이렇게 경로 변경만 되고 화면은 리렌더링 되지 않는 경우엔 어떻게 해결해야하나요?
react node.js seo graphql next.js
2023-09-20T11:49:32.270Z
댓글 0
좋아요 0
조회수 234
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
const 나의그래프큐엘셋팅 = gql` mutation createBoard($createBoardInput: CreateBoardInput!) { createBoard(createBoardInput: $createBoardInput) { _id } } `; 처음에 단순히 결과값을 _id 만을 받도록 코딩했었는데 이 결과 등록하기 버튼을 누르면 create 된 값이 화면에 리렌더링 되기는 했지만 글의 갯수가 10개로 고정이 됬습니다. 예를들어 이미 1,2,....,9,10 이라는 글이 화면에 보이는 상황에서 a라는 글을 추가하면 a,1,2,...,9,10 으로 화면이 보이는 것이 아니라 a,1,2...,8,9 까지만 보입니다. const 나의그래프큐엘셋팅 = gql` mutation createBoard($createBoardInput: CreateBoardInput!) { createBoard(createBoardInput: $createBoardInput) { _id writer title contents } } `; 그리고 다음과 같이 코드를 수정하게 되면 원하는 결과가 나오게 되었는데 무슨 차이가 있는 것일까요?
react node.js seo graphql next.js
kyb1208tg
2023-09-19T14:11:59.247Z
댓글 1
좋아요 0
조회수 262
미해결
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
안녕하세요 선생님! 강의 게시판 API 만들기 실습을 보고 ApolloServer 안에 cors: true를 적었는데 빨간 밑줄이 생기면서 ' { typeDefs: string; resolvers: { Query: { fetchBoards: () => Promise<Board[]>; }; Mutation: { createBoard: (parent: any, args: any, context: any, info: any) => Promise<string>; }; }; cors: boolean; }' 형식의 인수는 'ApolloServerOptions<any>' 형식의 매개 변수에 할당될 수 없습니다. 개체 리터럴은 알려진 속성만 지정할 수 있으며 'ApolloServerOptionsWithTypeDefs<any>' 형식에 'cors'이(가) 없습니다. 라고 오류가 떴는데 아무리 찾아봐도 해결방법을 몰라 글을 올리게 되었습니다
react node.js seo graphql next.js
Kim Siyoon
2023-09-19T07:07:27.662Z
댓글 1
좋아요 0
조회수 411
미해결
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
안녕하세요 강의를 들은 이후 나름 열심히 과제를 수행중이었는데, 도저히 해결되지 않는 문제도 있고, 피드백을 받고 싶어 질문을 남깁니다! 여성, 남성 선택 박스의 가운데 공백이 아무리 해도 생기질 않습니다. 2. 이용 약관 아래에 <hr> 태그가 먹히지 않습니다. 입력하면 줄이 생겨야하는데 생기지 않고 있어요. (정확한 위치는 사진 속 주석 참고 부탁드립니다.) 3. 아래쪽 전체적 간격이 뭔가 어정쩡한 느낌입니다.. 4. 코드를 보시고 혹시 제가 고쳐야 할 점이나, 공부가 필요한 부분이 있을까요?
react node.js seo graphql next.js
kannlann
2023-09-19T06:39:00.698Z
댓글 1
좋아요 0
조회수 623
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
프로젝트 전체 다운 받아서 보려고 하는데 git 주소 알려주세요
react node.js seo graphql next.js
tamo
2023-09-19T04:17:22.223Z
댓글 1
좋아요 0
조회수 369
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
Section 50 결제처리 레벨업 추가 학습 주제에서 포인트 충전 관련하여 문의드립니다. createPointTransactionsOfLoading에 API를 요청 했는데 404에러가 나옵니다! 아임포트(테스트용)로 결제 성공하였고 응답받은 impUid도 잘 추가하였고, accessToken도 헤더에 포함시켰습니다. 무슨 문제일까요?ㅠㅠ 요청 mutation mutation { createPointTransactionOfLoading(impUid: "imp_618843313239") { amount } } error메세지 { "errors": [ { "message": "Request failed with status code 404", "locations": [ { "line": 2, "column": 3 } ], "path": [ "createPointTransactionOfLoading" ], "extensions": { "code": "INTERNAL_SERVER_ERROR", "exception": { "stacktrace": [ "Error: Request failed with status code 404", " at Object.callErrorProcessor (/codecamp_backend_api/dist/common/libraries/errorProcessor.js:8:11)", " at CreatePointTransactionOfLoadingService.fetchPaymentFromImpUid (/codecamp_backend_api/dist/api/pointTransaction/services/mutation/createPointTransactionOfLoading.service.js:42:36)", " at runMicrotasks (<anonymous>)", " at processTicksAndRejections (internal/process/task_queues.js:93:5)", " at async target (/codecamp_backend_api/node_modules/@nestjs/core/helpers/external-context-creator.js:76:28)", " at async /codecamp_backend_api/node_modules/@nestjs/core/helpers/external-proxy.js:9:24" ] } } } ], "data": null
flfk55
2023-09-18T15:22:44.886Z
댓글 1
좋아요 0
조회수 246
미해결
[리뉴얼] React로 NodeBird SNS 만들기
안녕하세요! React로 NodeBird SNS 만들기 섹션1 프로필 페이지 만들기까지 수강한 수강생입니다! 제로초님 강의와 트위터 클론 깃허브를 확인해도 원인을 알 수 없어 질문 글 올립니다! 항상 강의 잘 보고 있습니다! 제로초님 항상 감사합니다! 사전에 antd 4버전, ant-design icons 4버전을 설치하였습니다. import { StopOutlined } from '@ant-design/icons'; 위처럼 ant-design icons를 설치했지만 앤트 디자인 아이콘이 뜨지 않습니다. 버전 문제라고 생각해 사이트에서 4버전의 StopOutlined 아이콘을 가져와 다시 시도했으나 같은 결과가 나타났습니다. FollowList.js FollowList 컴포넌트의 return 코드 중 의심되는 부분의 코드를 올립니다. renderItem={(item) => { <List.Item style={{ marginTop: 20 }}> <Card actions={[<StopOutlined key="stop" />]}> <Card.Meta description={item.nickname} /> </Card> </List.Item> }}
react redux node.js express next.js
이가은
2023-09-18T14:32:25.291Z
댓글 1
좋아요 1
조회수 566
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
프리캠프 css정렬강의에서 자식 box들을 정렬하기 위하여, 부모 box의 속성 및 값으로 display: flex을 먼저 쓰고, flex-direction : row로 할건지, flex-direction : column으로 할건지 결정하고. 이어 justify content나 align itmes등을 사용하던데 그럼, display: flex의 기능은 무엇인가요? display : flex 라는 코드 없이 위의 flex기능들을 구사하면 문제가 생기나요?? 시험삼아 display : flex 라는 코드 없이 뒤이어 flex-direction : row; justify items : center; align items : center; 라고 적고 확인해보니. 부모 박스 안에 자식 박스가 마치 flex-direction : column ; 만 실행된 것과 같은 효과가 나타났습니다.
react node.js seo graphql next.js
포켓몬마스터가될거야
2023-09-18T04:44:58.621Z
댓글 1
좋아요 0
조회수 557
미해결
[리뉴얼] React로 NodeBird SNS 만들기
안녕하세요! 강의를 어느정도 진행하고 프론트를 바꿔서 저만의 페이지를 구현하고 있습니다. 구현하던 중 LOAD_FOLLOWERS_REQUEST 요청을 보내면 계속 500 에러가 뜹니다. 프론트의 saga, Redux action 만드는 부분 확인했고, 백엔드 쪽에 routes확인했는데, 특별한 이상한 점을 못찾았습니다. * Front- redux/user * Front-saga/user * Back-routes * console *redux error log. 어디 부분에서 에러가 나는것일까요? 감사합니다.
react redux node.js express next.js
Spencer Kwon
2023-09-17T16:44:38.039Z
댓글 1
좋아요 0
조회수 398
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
안녕하세요. 포트폴리오를 만들던 도중 제 스스로 해결되지 않아 질문드립니다. import { useForm } from "react-hook-form"; import { wrapFormAsync } from "../../../../../../commons/libraries/asyncFunc"; import { yupResolver } from "@hookform/resolvers/yup"; import { productRegisterSchema } from "../../../../../commons/validation/Main"; import InputLong from "../../../../../commons/Input/long"; import Textarea01 from "../../../../../commons/Input/textarea"; import Button01 from "../../../../../commons/button/01"; import InputLongNormal from "../../../../../commons/Input/longNormal"; import { gql, useMutation } from "@apollo/client"; import type { IMutation, IMutationCreateUseditemArgs, } from "../../../../../../commons/types/generated/types"; import { useRouter } from "next/router"; import ImageUpload01 from "../../../../../commons/imageUpload/imageUpload"; interface IFormData { name: string; remarks: string; contents: string; price: number; images: string[]; } export const CREATE_USED_ITEM = gql` mutation createUseditem($createUseditemInput: CreateUseditemInput!) { createUseditem(createUseditemInput: $createUseditemInput) { _id } } `; export default function ProductRegisterBody(): JSX.Element { const { register, handleSubmit, formState } = useForm<IFormData>({ resolver: yupResolver(productRegisterSchema), mode: "onChange", }); const router = useRouter(); const [createUseditem] = useMutation< Pick<IMutation, "createUseditem">, IMutationCreateUseditemArgs >(CREATE_USED_ITEM); const onClickSubmit = async (data: IFormData): Promise<void> => { console.log(data); await createUseditem({ variables: { createUseditemInput: { name: data.name, remarks: data.remarks, contents: data.contents, price: data.price, images: data.images, }, }, }); void router.push("/markets"); }; return ( <form onSubmit={wrapFormAsync(handleSubmit(onClickSubmit))}> <InputLong register={register("name")} tag="상품명" /> <div>{formState.errors.name?.message}</div> <InputLong register={register("remarks")} tag="한줄요약" /> <div>{formState.errors.remarks?.message}</div> <Textarea01 register={register("contents")} tag="상품설명" /> <div>{formState.errors.contents?.message}</div> <InputLong register={register("price")} tag="판매가격" /> <div>{formState.errors.price?.message}</div> <InputLongNormal tag="태그입력" /> <div>거래위치</div> <div> <p>사진첨부</p> <ImageUpload01 register={register("images")} /> </div> <button> 테스트</button> <Button01 title="등록하기" isActive={formState.isValid} onClick={onClickSubmit} /> </form> ); } import { useMutation } from "@apollo/client"; import { useState, type ChangeEvent, useRef } from "react"; import { UPLOAD_FILE } from "../upload01/Upload01.queries"; import type { IMutation, IMutationUploadFileArgs, } from "../../../commons/types/generated/types"; import * as S from "./styles"; import type { UseFormRegisterReturn } from "react-hook-form"; interface IInputProps { register: UseFormRegisterReturn; } export default function ImageUpload01(props: IInputProps): JSX.Element { const [image, setImage] = useState(""); const [images, SetImages] = useState(""); const fileRef = useRef<HTMLInputElement>(null); const [uploadFile] = useMutation< Pick<IMutation, "uploadFile">, IMutationUploadFileArgs >(UPLOAD_FILE); const onChangeImageFile = async ( event: ChangeEvent<HTMLInputElement>, ): Promise<void> => { const file = event.target.files?.[0]; const result = await uploadFile({ variables: { file } }); console.log(result.data?.uploadFile.url); SetImages(result?.data?.uploadFile?.url ?? ""); }; console.log(images); const onClickFile = (): void => { fileRef.current?.click(); }; return ( <> <S.Wrapper> <S.Image src={`https://storage.googleapis.com/${images}`} alt="" /> <S.ImageClick onClick={onClickFile}> +</S.ImageClick> <S.HiddenInput onChange={onChangeImageFile} type="file" ref={fileRef} /> <S.HiddenInput value={images} {...props.register} autoFocus name="images" /> </S.Wrapper> </> ); } 일단 요령이 없어서 아래 처럼 만들었습니다. 사진을 올리면 register를 위해 value값이 변경되는 input창을 만들었으나 등록하기를 누르면 graphql에 업로드되지가 않습니다. {price: 333, contents: '3333', remarks: '333', name: '333', images: ''} 허나 저 빨간 v표시 친 부분을 한번 클릭한다면 {price: 33, contents: '3333', remarks: '333', name: '3333', images: 'codecamp-file-storage/2023/9/17/Vector.png'} 다음처럼 images가 잘 입력됩니다. 클릭하지 않아도 자동으로 변경되면 images를 업로드 시킬 수 있는 방법이 있을까요? 아니면 참고할만한 다른 방법들이 있을까요?
react node.js seo graphql next.js
dlwjdgus3217
2023-09-17T16:05:59.765Z
댓글 2
좋아요 0
조회수 508
해결됨
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 강의 마지막에 beforeEach 메소드를 추가하여 매번 객체를 생성하게 되잖아요. 그러면 굳이 afterEach() 메소드로 매번 clear할 필요가 없다고 생각했었는데 afterEach() 메소드를 주석 처리하면 오류가 나더라고요. 제 생각엔 MemoryMemberRepository의 store 변수가 static이기 때문에 beforeEach() 메소드로 매번 객체를 새로 생성하더라도 static 변수는 새로 생기지 않고 기존의 것이 계속 공유되고 있기 때문에 afterEach()가 필요한 거 아닐까 싶은데 제가 정확히 이해한 게 맞는지, 제 생각에 오류가 있는지 궁금합니다.
11 1
2023-09-17T12:14:00.595Z
댓글 2
좋아요 3
조회수 598
해결됨
[리뉴얼] React로 NodeBird SNS 만들기
섹션6까지 끝낸 상태입니다 기능에는 문제가 없는데 웹사이트 첫 방문으로 로그아웃 상태로 프로필 페이지에 들어가면 아래와 같은 경고가 뜹니다. 찾아보니 컴포넌트에서 setState나 dispatch를 useEffect나 이벤트 함수 없이 컴포넌트에서 그냥? 실행해서 생기는 경고인 듯한데 제 코드에는 그런게 없어서 오리무중입니다. 이 경고가 왜 뜨는건지, 무시해도 되는지, 어떻게 해결해야하는지 몰라서 질문 남깁니다. (수정-배포버전에서는 안 뜹니다) (참고로 쓰로틀링을 5초로 설정해서 페이지 이동 시간이 5초 걸렸을때는 페이지 이동시 종종 Cannot update a componet (`AppLayout`) ~~~ inside `Nodebird 와 같은 경고도 발생했습니다 쓰로틀링을 없애니 발생하지 않네요) _app.jsx import PropTypes from 'prop-types'; import Head from 'next/head'; import { Provider } from 'react-redux'; import wrapper from '../store/configureStore'; const NodeBird = ({ Component, ...rest }) => { const { store, props } = wrapper.useWrappedStore(rest); return ( <Provider store={store}> <Head> <meta charSet="utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>NodeBird</title> </Head> <Component {...props.pageProps} /> </Provider> ); }; NodeBird.propTypes = { Component: PropTypes.elementType.isRequired, }; export default NodeBird; profile.jsx import Head from 'next/head'; import { useEffect, useState, useCallback } from 'react'; import { useSelector } from 'react-redux'; import Router from 'next/router'; import axios from 'axios'; import { END } from 'redux-saga'; import useSWR from 'swr'; import AppLayout from '../components/AppLayout'; import NicknameEditForm from '../components/NicknameEditForm'; import FollowList from '../components/FollowList'; import { LOAD_MY_INFO_REQUEST } from '../reducers/user'; import wrapper from '../store/configureStore'; import { backUrl } from '../config/config'; const fetcher = (url) => axios.get(url, { withCredentials: true }).then((result) => result.data); const Profile = () => { const { me } = useSelector((state) => state.user); const [followersLimit, setFollowersLimit] = useState(3); const [followingsLimit, setFollowingsLimit] = useState(3); const { data: followersData, error: followerError } = useSWR(`${backUrl}/user/followers?limit=${followersLimit}`, fetcher); const { data: followingsData, error: followingError } = useSWR(`${backUrl}/user/followings?limit=${followingsLimit}`, fetcher); useEffect(() => { if (!me?.id) { // 로그아웃했을때 Router.replace('/'); } }, [me?.id]); const loadMoreFollowers = useCallback(() => { setFollowersLimit((prev) => prev + 3); }, []); const loadMoreFollowings = useCallback(() => { setFollowingsLimit((prev) => prev + 3); }, []); if (!me) { return null; } if (followerError || followingError) { console.error(followerError || followingError); return <div>팔로잉/팔로워 로딩 중 에러가 발생합니다</div>; } return ( <> <Head> <title>내 프로필 | NodeBird</title> </Head> <AppLayout> <NicknameEditForm /> <FollowList header="팔로잉" data={followingsData} onClickMore={loadMoreFollowings} loading={!followingsData && !followingError} /> <FollowList header="팔로워" data={followersData} onClickMore={loadMoreFollowers} loading={!followersData && !followerError} /> </AppLayout> </> ); }; export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => { axios.defaults.headers.Cookie = req?.headers.cookie; store.dispatch({ type: LOAD_MY_INFO_REQUEST, }); store.dispatch(END); await store.sagaTask.toPromise(); }); export default Profile;
react redux node.js express next.js
박규석
2023-09-17T08:02:39.761Z
댓글 1
좋아요 0
조회수 343
해결됨
[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
강의에서처럼 이미지를 클릭해도 오른쪽 하단에 css 정보가 안보여요..
react node.js seo graphql next.js
박주연
2023-09-16T17:36:01.241Z
댓글 1
좋아요 0
조회수 657
미해결
따라하며 배우는 리액트 A-Z[19버전 반영]
구글링을 해서 폐쇄망에 react 프로젝트를 어찌어찌 설치를 했습니다. 정상적으로 실행도 되고 프로그래밍도 가능합니다. 근데, 중간에 패키지를 추가하려고 인터넷이 가능한 곳에서 패키지를 추가해서 옮겨보려 했으나 잘 안되더군요. 폐쇄망에서 패키지 추가는 어떻게 해야 하는지 도움 부탁드립니다.
react redux tdd typescript next.js 소프트웨어-테스트 오프라인 폐쇄망
metlin
2023-09-16T17:01:33.197Z
댓글 1
좋아요 0
조회수 1166
해결됨
[리뉴얼] React로 NodeBird SNS 만들기
안녕하세요 제로초님 강의듣고 리덕스, 사가 대신 툴킷과 내장 썽크를 사용해서 다시 만들어보는 중인데 게시글 등록시 글은 정상적으로 등록이 되는데 게시글 갯수가 실시간으로 바뀌지 않고 새로고침 해야 반영이 됩니다. 삭제할때도 정상적으로 삭제는 되는데 새로고침해야 삭제된 결과가 반영이 됩니다. 백엔드 부분은 강의와 같이 js로 작성했고 게시글 작성 툴킷은 다음과 같이 코드작성했습니다. // toolkit/post.ts export const initialState: PostState = { // 기본값 mainPosts: [], imagePaths: [], postAdded: false, // 게시글 로딩 loadPostLoading: false, loadPostDone: false, loadPostError: null, // 추가 로딩 hasMorePosts: false, // 게시글 작성 addPostLoading: false, addPostDone: false, addPostError: null, // 게시글 삭제 removePostLoading: false, removePostDone: false, removePostError: null, export const addPostAction = createAsyncThunk( 'post/addPost', async (data: FormData) => { const response = await axios.post('/post', data); return response.data; } ); export const removePostAction = createAsyncThunk( '/post/delete', async (data: number) => { const response = await axios.delete(`/post/${data}`); return response.data; } ); extraReducers: (builder) => { builder // 게시글 추가 .addCase(addPostAction.pending, (draft) => { draft.addPostLoading = true; draft.addPostDone = false; draft.addPostError = null; }) .addCase(addPostAction.fulfilled, (draft, action) => { draft.addPostLoading = false; draft.addPostDone = true; draft.mainPosts.unshift(action.payload); }) .addCase(addPostAction.rejected, (draft, action) => { draft.addPostLoading = false; draft.addPostError = action.error.message; }) // 게시글 삭제 .addCase(removePostAction.pending, (draft) => { draft.removePostLoading = true; draft.removePostDone = false; draft.removePostError = null; }) .addCase(removePostAction.fulfilled, (draft, action) => { draft.removePostLoading = false; draft.removePostDone = true; draft.mainPosts = draft.mainPosts.filter( (v) => v.id !== action.payload ); }) .addCase(removePostAction.rejected, (draft, action) => { draft.removePostLoading = false; draft.removePostError = action.error.message; }) 이해가 안가는 부분이 post에서 게시글 삭제, 입력등의 작업을 하고 user에서 회원가입,로그인,로그아웃, 팔로우 등의 작업을 하게 나눠놨는데 게시글 입력할때 mainPosts의 값이 추가될때마다 그 값이 컴포넌트에서 불러와져서 화면의 게시글 갯수 부분이 바뀌는건 이해가 가는데 // pages/index.ts const Home = () => { const { mainPosts, hasMorePosts, loadPostLoading } = useSelector( (state: RootState) => state.post ); {me && <PostForm />} {mainPosts.map((post) => ( <PostCard key={post.id} post={post} /> ))} 이 부분에서 /component/UserProfile.tsx const UserProfile = () => { const { me, logOutLoading } = useSelector((state: RootState) => state.user); return ( <> <Card actions={[ <div key='twit'> 짹짹 <br /> {me?.Posts.length} </div>, <div key='follower'> 팔로워 <br /> {me?.Followings.length} </div>, <div key='following'> 팔로잉 <br /> {me?.Followers.length} </div>, ]} > me는 툴킷의 user.ts 의 me를 참조하는거 아닌가요? 게시글 입력,삭제시 post.ts를 통해 post.ts의 mainPosts 값이 바뀌는데 user.ts를 참조하는 컴포넌트에서 me.Posts.length 값이 바뀌는 부분이 잘 이해가 가질 않습니다. 그리고 댓글 삭제기능을 추가하고 싶은데요. //pages/index.ts const { mainPosts, hasMorePosts, loadPostLoading } = useSelector( (state: RootState) => state.post ); {mainPosts.map((post) => ( <PostCard key={post.id} post={post} /> ))} //component/PostCard.tsx const { removePostLoading } = useSelector((state: RootState) => state.post); const onRemovePost = useCallback(() => { dispatch(removePostAction(post.id)); }, []); // post.ts export const removePostAction = createAsyncThunk( '/post/delete', async (data: number) => { const response = await axios.delete(`/post/${data}`); return response.data; } ); .addCase(removePostAction.fulfilled, (draft, action) => { draft.removePostLoading = false; draft.removePostDone = true; draft.mainPosts = draft.mainPosts.filter( (v) => v.id !== action.payload ); }) //back/routes/post router.delete('/:postId', isLoggedIn, async (req, res, next) => { try { await Post.destroy({ where: { id: req.params.postId, UserId: req.user.id }, }); res.status(200).json({ PostId: parseInt(req.params.postId, 10) }); } catch (err) { console.error(err); next(err); } }); 게시글을 삭제할때는 post.id로 해당하는 글의 id를 바로 보내서 삭제할수 있는건 이해가 가는데 comment의 경우 [{댓글1}, {댓글2}] 형식으로 각 댓글의 값이 들어있어서 이부분을 어떻게 해야할지 감이 잡히지 않습니다.
react redux node.js express next.js
ㅇㅅㅇ?
2023-09-16T08:53:10.424Z
댓글 1
좋아요 0
조회수 505