인프런 커뮤니티 질문&답변

선종원님의 프로필 이미지
선종원

작성한 질문수

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

proxy 객체

작성

·

356

0

댓글작성 기능을 구현중에 있는데요

saga 백엔드까지는 요청응답은 잘 작동하고

reducer에서 draft.userPost.find로 postid찾고 거기에 댓글 더하려고 하는데 잘 안되서 console로 찍어보니까

draft.userPost, draft.userPost[action.data.postId - 1], find 메소드써도 아래처럼 proxy객체로 나오는데

이런 경우엔 어떻게 접근해야 되나요?

댓글 작성하라는 요청보냈을 때, 응답오는 data는 { id: 1, content: "aaa", UserId: 1, PostId: 1 } 이런식입니다

답변 22

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

through: { attributes: ['UserId'] }

as Likes 아래에 넣어주세요.

그리고 질문 주제가 달라지면 새 질문에 달아주시면 좋겠습니다. 알림이 와도 찾기가 좀 힘듭니다.

0

선종원님의 프로필 이미지
선종원
질문자

get post 할때 아래 코드처럼 작성하면 관계가 있는 like 테이블에 모든 정보를 다 가져오는데 UserId만 가져오고 싶다면 어떻게 작성해야되나요?

{

model: User,

as: 'Likes'

}

0

선종원님의 프로필 이미지
선종원
질문자

감사합니다!

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

event.target.files는 null이 될 가능성도 있으므로 event.target.files?.[0] 하시면 됩니다.

좀 더 정확하게는 if문으로 event.target.files.length가 존재할 때 업로드하는 방식도 있습니다.

0

선종원님의 프로필 이미지
선종원
질문자

이렇게 하면 되는건가요?

뒤에 [0]을 지우게되면 아래와 같이 뜹니다  null체킹하면 되나요?

타입스크립트가 좀 골치아프긴하네요

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

아, 제가 착각을 한 게 하나 있네요. event.target.files는 항상 배열입니다.

거기서 첫 번째 것 꺼내서 넣어보세요. event.target.files[0]

그리고 원인을 알았습니다.

지금 서버로 폼데이터를 보내고 있지 않으시네요.

uploadProfileImageRequest(imageData) 하셔야 합니다.

{ imageData, id: userState?.id } 하는 순간 폼데이터가 아니라 json을 보내시는 겁니다.

id도 같이 보내고 싶으시면

imageData.append('id', userState?.id) 하세요.

0

선종원님의 프로필 이미지
선종원
질문자

file에서 빨간줄 에러뜨길래 event 타입을 any로 바꿔서 이미지 올려봤더니 에러코드 500뜨면서 오류가 납니다

요청 페이로드에 빈 객체만 전달되네요

input에는 아예 multiple도 없습니다

event타입이 React.ChangeEvent<HTMLInputElement>일 때,  event.target.files 로 바꾸면 

↓ wrapper => form, input => input

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

이미지 한 장만 선택하시면 event.target.files가 아니라 event.target.file이 되어야 합니다. 그리고 input 태그에서도 multiple을 제거하셔야 하고요.

하나를 올리는 데 반복문을 사용할 필요는 없겠죠?

image.append('profileImage', event.target.file)하면 됩니다.

0

선종원님의 프로필 이미지
선종원
질문자

네 이미지 한 장만 올립니다.

여기서 어떻게 수정을 해줘야되나요?
그냥 [].forEach.call 을 쓰면 에러가 떠서 a.forEach.call로 쓰고 있습니다.

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

사진을 한 장 올리시는 것 맞나요? 프론트 코드보면 여러 장올리는 코드로되어있습니다. 여러 장 올리실 때는 req.files에 있는데 이 때는 코드 수정을 제 소스코드처럼 해야합니다.

한장 올리시는거면 프론트를 수정하셔야 할듯합니다.

0

선종원님의 프로필 이미지
선종원
질문자

이런 메시지가 뜨는데 어떻게해야되나요?

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

req.file.filename 적어주시면 됩니다.

multer는 upload.single 안에 들어있는 키와 일치하는 데이터는 알아서 업로드 후 req.file로 보내고 나머지 데이터는 req.body로 보냅니다.

0

선종원님의 프로필 이미지
선종원
질문자

프로필 사진업로드를 구현중인데 뭔가 잘 이해가 안가서 질문드립니다

프론트 이미지 보내는 함수

  const handleChange = useCallback(
    (eventReact.ChangeEvent<HTMLInputElement>) => {
      const imageData = new FormData();
      let aany[] = [];
      a.forEach.call(event.target.files, (info=> {
        imageData.append('profileImage'info);
      });
      dispatch(uploadProfileImageRequest({ imageDataid: userState?.id }));
    },
    [dispatchuserState],
 );

백엔드 이미지 받는 라우터

// ADD PROFILE IMAGE
const upload = multer({
  storage: multer.diskStorage({
    destination(reqfiledone) {
      done(null'./server/upload');
    },
    filename(reqfiledone) {
      const ext = path.extname(file.originalname);
      const basename = path.basename(file.originalnameext);
      console.log(basenameext);
      done(nullbasename + '_' + new Date().getTime() + ext);
    },
  }),
  limits: { fileSize: 20 * 1024 * 1024 },
});
router.post(
  '/profileImage',
  isLogin,
  upload.single('profileImage'),
  async (reqresnext=> {
    // POST /user/profileImage
    try {
      console.log(req.body.imageData);
      const user = await User.findOne({ where: { id: req.body.id } });
      const profile = await ProfileImage.create({
        src: ???,
        UserId: user.id,
      });
      res.json({ src: profile.srcid: req.body.id });
    } catch (err) {
      console.error(err);
      next(err);
    }
  },
);

백엔드에서 감이 좀 잘 안 잡히는데 일단은 프론트에서 { ImageData, id: ~~ } 이 부분은 UserId 컬럼을 채우기 위해서 보내줬습니다

ProfileImage 테이블에 컬럼은  id, src, createdAt, updatedAt, UserId 가 있습니다.

1. src 부분에 뭘 넣어줘야 할지 모르겠습니다. 

ProfileImage.create({

  src: ??? 

})

2. 이미지랑 UserId를 같이 보내줘도  multer에서 알아서 이미지만 골라서 로컬에 저장해주나요?

0

선종원님의 프로필 이미지
선종원
질문자

아...정말 죄송합니다. 글 남기는거 깜빡했네요;;; 시간 헛되게 해서 죄송합니다ㅜㅜ

case ADD_COMMENT_SUCCESS: {
        draft.userPost
          .find((i=> i.id === action.data.PostId)
          .Comments.push(action.data);
        draft.addCommentLoading = false;
        draft.addCommentDone = true;
        draft.addCommentError = null;
        break;
     }

이렇게 연속으로 접근해서 했더니 성공했습니다.

지금은 수많은 오류를 헤쳐나가면서 다른 기능 구현하고 있습니다. (예를 들어 수정 삭제 가져오기 등등...)

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

https://www.inflearn.com/questions/77748

비슷한 질문이 있어서 어떻게 해결하셨는지 찾아봤습니다. 직접 map을 통해 불변성을 해제하셨는데요. 사실 이런 상황이 나와서는 안 되지만 임시 방편으로 시도해볼만 합니다.

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

제 기존 코드의 Action과 Diff 부분입니다. ADD_COMMENT_SUCCESS가 뜰 때 Action의 data에 댓글이 들어있고, diff에서 저렇게 추가됐다는 것이 보여야 합니다.

제 코드와는 mainPosts -> userPost 이 부분만 다른데 이 부분은 다르게 구현하셨나보네요.

0

선종원님의 프로필 이미지
선종원
질문자

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

ADD_COMMENT_SUCCESS 리듀서 부분 보여주세요.

0

선종원님의 프로필 이미지
선종원
질문자

명확하게 콘솔에러 뭐 이런거 있으면 캡쳐해서 올려드리겠는데 브라우저 콘솔에도 에러고 경고고 아무것도 안뜨고

네트워크탭에서도 정상적으로 HTTP 200 OK 해서 데이터로 잘 받아옵니다.

그래도 증상만 먼저 구체적으로 말씀드리면...

1. 댓글작성 -> 작성버튼 누름 -> addCommentRequest(데이터) 보내면 데이터도 제대로 들어있습니다.

2.리덕스 개발자도구로 보면  ADD_COMMENT_REQUEST 실행되고 saga에서도 result.data 콘솔찍어보면 제대로 나옵니다. 그 다음에 SUCCESS도 실행됐을 때

3. 여기서 state항목을 보면 {id: 39 content: 어쩌고} 이것이 실시간으로 더해져서 나와야하는데 38에서 그대로 머물러 있고 갱신이 안됩니다

여기서 갱신을 하고 싶으면 F5눌러서 페이지를 새로고침을 해야 됩니다

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

그러니까 정확히 어떤 에러가 표시되는 건가요?

ㅇㄹㅇㄹ

ㅇㄹ

0

선종원님의 프로필 이미지
선종원
질문자

네 unshift나 push나 concat도 적용이 안됩니다

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

immer는 저렇게 proxy 객체가 나오는 게 맞슺니다. 저렇게 찾고 나서 댓글에 push같은 메서드가 먹지 않는 것인가요?

선종원님의 프로필 이미지
선종원

작성한 질문수

질문하기