강의

멘토링

커뮤니티

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

hib4888님의 프로필 이미지
hib4888

작성한 질문수

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

게시글 불러오기

saga의 loadPostsAPI 함수 실행 질문드립니다.

해결된 질문

작성

·

303

0

안녕하세요 제로초님 강의잘듣고있습니다.

게시글을 불러올 때 saga에서 다음과 같은 에러가 발생하면서 loadPostsAPI 함수가 실행이 안되서 질문드립니다.

콘솔의 오류를 확인해보니 data속성을 읽을 수 없어서 LOAD_POSTS_FAILURE에서 error를 출력합니다.

강의내용의 코드와 다른점이 없는것같은데 혹시 이문제에 대해 알 수 있을까요?

Recipe.io - Chrome 2022-09-19 오후 2_10_26 (2).pngRecipe.io - Chrome 2022-09-19 오후 2_10_29 (2).pngRecipe.io - Chrome 2022-09-19 오후 2_10_40 (2).pngRecipe.io - Chrome 2022-09-19 오후 2_10_54 (2).pngpost.js - prepare - Visual Studio Code [Administrator] 2022-09-19 오후 2_13_59 (2).png

참코 코드도 같이 첨부하겠습니다.

reducers/post.js

const reducer = (state = initialState, action) => {
  return produce(state, (draft) => {
    switch (action.type) {
      case LOAD_POSTS_REQUEST:
        draft.loadPostsLoading = true;
        draft.loadPostsDone = false;
        draft.loadPostsError = null;
        break;
      case LOAD_POSTS_SUCCESS:
        draft.loadPostsLoading = false;
        draft.loadPostsDone = true;
        draft.firstPageLoad = false;
        draft.mainPosts = draft.mainPosts.concat(action.data);
        draft.hasMorePosts = draft.mainPosts.length < 30;
        break;
      case LOAD_POSTS_FAILURE:
        draft.loadPostsLoading = false;
        draft.loadPostsError = action.error;
        break;

sagas/post.js

import { all, fork, delay, put, takeLatest, call } from 'redux-saga/effects';
import shortId from 'shortid';
import axios from 'axios';

import {
  LOAD_POSTS_REQUEST, LOAD_POSTS_SUCCESS, LOAD_POSTS_FAILURE, 
} from '../reducers/post';

function loadPostsAPI() {  
  console.log('사가 실행2');
  return axios.get('/posts');
}

function* loadPosts() {   
  try {    
    console.log('사가 실행1');
    const result = yield call(loadPostsAPI, action.data); 
    yield put({
      type: LOAD_POSTS_SUCCESS,
      data: result.data,
    })
  } catch(err) {
    yield put({ 
      type: LOAD_POSTS_FAILURE,
      data: err.response.data 
    })
  }  
}

function* watchLoadPosts() {  
  yield takeLatest(LOAD_POSTS_REQUEST, loadPosts);
}

export default function* postSaga() {
  yield all([
    fork(watchLoadPosts),
  ]);
}

 

routes/posts.js

const express = require('express');

const { Post, User, Image, Comment } = require('../models');

const router = express.Router();

router.get('/', async (req, res, next) => {
  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'],
        }],
      }],
    });
    console.log(posts);
    res.status(200).json(posts);
  } catch (error) {
    console.error(error);
    next(error);
  }
});

module.exports = router;

답변 1

0

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

서버로 요청이 아예 안 간 것 같은데 네트워크 탭 켜놓고 다시 한 번 해보시겠어요?

hib4888님의 프로필 이미지
hib4888
질문자

서버를 재실행하고 네트워크탭을 확인해보니 말씀대로 요청이 안보입니다.

redux 툴에서는 LOAD_POSTS_REQUEST 가 정상적으로 실행됬는데

터미널이나 콘솔에서도 명확한 이유를 찾기가 힘드네요 ㅜㅜ

 

image

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

그 전에 load_my_info_success는 리덕스에 찍히나요?

hib4888님의 프로필 이미지
hib4888
질문자

첫 빌드시 로그인을 하지 않은 상태에서도 LOAD_MY_INFO_REQUEST를 실행해서

코드를 다음과 같이 수정했습니다.

pages/index.js

import React, { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Button } from 'antd';
import { PlusCircleOutlined } from '@ant-design/icons';
import Link from 'next/link';

import { 
  HomeWrapper, HomeLogoHeader, HomeLogoText, PageMainText, PageSubText, HomeInputWrapper
} from '../pagestyles';
import { LOAD_POSTS_REQUEST } from '../reducers/post';
import { LOAD_MY_INFO_REQUEST } from '../reducers/user';
import AppLayout from '../components/AppLayout/';
import PostList from '../components/HomePost/PostList';
import HomeFooter from '../components/HomePost/HomeFooter';

const Home = () => {
  const dispatch = useDispatch();
  const { me, logInDone } = useSelector((state) => state.user);
  const { mainPosts, firstPageLoad, hasMorePosts, loadPostsLoading } = useSelector((state) => state.post);
  
  const onSearch = useCallback((value) => {
    console.log(value);
  }, []);

  // 로그인한상태에서만 실행하게 수정
  useEffect(() => {
    if (logInDone) {
      dispatch({
        type: LOAD_MY_INFO_REQUEST
      });
    }
  }, [logInDone]);

  useEffect(() => {
    if (firstPageLoad) {
      dispatch({
        type: LOAD_POSTS_REQUEST
      });
    }
  }, []);

  useEffect(() => {
    function onScroll() {
      if (window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300) {
        if (hasMorePosts && !loadPostsLoading) {
          dispatch({
            type: LOAD_POSTS_REQUEST
          });    
        }
      }
    };    

    window.addEventListener('scroll', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
    }
  }, [hasMorePosts, loadPostsLoading]);
  
  return (    
    <AppLayout>
      <HomeWrapper>
        <HomeLogoHeader>
          <HomeLogoText>
            <PageMainText>Recipe.io</PageMainText>
            <PageSubText>Have a delicious meal today</PageSubText>
          </HomeLogoText>
          {me && <Link href='/posting'><a><Button type='primary' size='large' icon={<PlusCircleOutlined />} >Create Recipe</Button></a></Link>}
        </HomeLogoHeader>
        
        <HomeInputWrapper 
          placeholder="Search for Recipe" 
          size='large' 
          allowClear="true" 
          enterButton 
          onSearch={onSearch}
        />
        
        <PostList mainPosts={mainPosts} />
      </HomeWrapper>

      <HomeFooter />
    </AppLayout>
  )
};

export default Home;

 

이후 콘솔이랑 redux툴을 확인해도 이전과는 동일하네요 ㅜㅜ

imageimageimage

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

찾았습니다. action.data 넣으셔서 그렇습니다. *loadPosts 매개변수에 action이 없거든요

hib4888님의 프로필 이미지
hib4888
질문자

하루종일 계속 찾고 있었는데 드디어 답을 알았네요 감사합니다 ㅜㅜ

 

hib4888님의 프로필 이미지
hib4888

작성한 질문수

질문하기