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

박지연님의 프로필 이미지
박지연

작성한 질문수

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

서버에러와ReferenceError 질문드립니다

해결된 질문

작성

·

319

0

선생님께 배운 코드를 응용해서 만드는 중에

posts/index.js에 post를 사용하려고 작성하였는데 찾을 수 없다는 에러가 발생하였습니다..

그리고 백엔드 서버는 사용하지두 않았는데 서버에러가 발생하네요

첫 메인화면 띄우는 것부터 문제가 발생해서 로그인이나 회원가입처럼 액션문제는 아닌것같은데 찾기가 너무 어려워서 도움을 요청드립니다..

 스크린샷 2022-10-08 오후 10.07.15.png

스크린샷 2022-10-08 오후 10.07.08.png

 

//posts/_app.js
import PropTypes from "prop-types";
import Head from "next/head";
import "../styles/global.css";

import wrapper from "../store/configureStore";

function App({ Component }) {
  return (
    <>
      <Head>
        <meta charSet="utf-8" />
        <title>Foodi:e</title>
      </Head>
      <Component />
    </>
  );
}
App.propTypes = {
  Component: PropTypes.elementType.isRequired,
};
export function reportWebVitals(metric) {
  console.log(metric);
}

export default wrapper.withRedux(App);
//reducers/index.js
import { HYDRATE } from "next-redux-wrapper";
import { combineReducers } from "redux";

import user from "./user";
import post from "./post";

// (이전상태, 액션) => 다음상태
const rootReducer = (state, action) => {
  switch (action.type) {
    case HYDRATE:
      console.log("HYDRATE", action);
      return action.payload;
    default: {
      const combinedReducer = combineReducers({
        user,
        post,
      });
      return combinedReducer(state, action);
    }
  }
};

export default rootReducer;
//reducers/post.js
import shortId from "shortid";
import faker from "@faker-js/faker";

import produce from "../util/produce";

export const initialState = {
  mainPosts: [],
  imagePaths: [],
  hasMorePosts: true,
  loadPostsLoading: false,
  loadPostsDone: false,
  loadPostsError: null,
  addPostLoading: false,
  addPostDone: false,
  addPostError: null,
  removePostLoading: false,
  removePostDone: false,
  removePostError: null,
  addCommentLoading: false,
  addCommentDone: false,
  addCommentError: null,
};

export const generateDummyPost = (number) =>
  Array(number)
    .fill()
    .map(() => ({
      id: shortId.generate(),
      User: {
        id: shortId.generate(),
        nickname: faker.name.findName(),
      },
      content: faker.lorem.paragraph(),
      Images: [
        {
          src: faker.image.image(),
        },
      ],
      Comments: [
        {
          User: {
            id: shortId.generate(),
            nickname: faker.name.findName(),
          },
          content: faker.lorem.sentence(),
        },
      ],
    }));

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,
});

export const addComment = (data) => ({
  type: ADD_COMMENT_REQUEST,
  data,
});

const dummyPost = (data) => ({
  id: data.id,
  content: data.content,
  User: {
    id: 1,
    nickname: "delay",
  },
  Images: [],
  Comments: [],
});

const dummyComment = (data) => ({
  id: shortId.generate(),
  content: data,
  User: {
    id: 1,
    nickname: "delay",
  },
});
// 이전 상태를 액션을 통해 다음 상태로 만들어내는 함수(불변성은 지키면서)
const reducer = (state = initialState, action) =>
  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.mainPosts = action.data.concat(draft.mainPosts);
        draft.hasMorePosts = draft.mainPosts.length < 50;
        break;
      case LOAD_POSTS_FAILURE:
        draft.loadPostsLoading = false;
        draft.loadPostsError = action.error;
        break;
      case ADD_POST_REQUEST:
        draft.addPostLoading = true;
        draft.addPostDone = false;
        draft.addPostError = null;
        break;
      case ADD_POST_SUCCESS:
        draft.addPostLoading = false;
        draft.addPostDone = true;
        draft.mainPosts.unshift(dummyPost(action.data));
        break;
      case ADD_POST_FAILURE:
        draft.addPostLoading = false;
        draft.addPostError = action.error;
        break;
      case REMOVE_POST_REQUEST:
        draft.removePostLoading = true;
        draft.removePostDone = false;
        draft.removePostError = null;
        break;
      case REMOVE_POST_SUCCESS:
        draft.removePostLoading = false;
        draft.removePostDone = true;
        draft.mainPosts = draft.mainPosts.filter((v) => v.id !== action.data);
        break;
      case REMOVE_POST_FAILURE:
        draft.removePostLoading = false;
        draft.removePostError = action.error;
        break;
      case ADD_COMMENT_REQUEST:
        draft.addCommentLoading = true;
        draft.addCommentDone = false;
        draft.addCommentError = null;
        break;
      case ADD_COMMENT_SUCCESS: {
        const post = draft.mainPosts.find((v) => v.id === action.data.postId);
        post.Comments.unshift(dummyComment(action.data.content));
        draft.addCommentLoading = false;
        draft.addCommentDone = true;
        break
      }
      case ADD_COMMENT_FAILURE:
        draft.addCommentLoading = false;
        draft.addCommentError = action.error;
        break;
      default:
        break;
    }
  });

export default reducer;
//posts/index.js
function Home() {
  const dispatch = useDispatch();
  const { me } = useSelector((state) => state.user);
  const { mainPosts } = useSelector(
    (state) => state.post
  );
  

  return (
    <>
      <Header />
      <Nav />

      {mainPosts.map((post) => (
        <DeskLatestPost post={post} />
      ))}
      <DeskLatestPost post={post} />

      <Footer />
    </>
  );
}

export default Home;
//store/configureStore.js
import { createWrapper } from "next-redux-wrapper";
import { applyMiddleware, compose, createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import createSagaMiddleware from "redux-saga";

// 미들웨어는 리덕스 기능을 확장시켜주는 느낌!
import reducer from "../reducers";
import rootSaga from "../sagas";

function configureStore({ context }) {
  console.log(context);
  const sagaMiddleware = createSagaMiddleware();
  // 미들웨어 작성 ~~ ? 배포용 : 개발용
  //   배포할때 변동사항이 노출되면 안되므로 개발용에만 보이도록!
  const middlewares = [sagaMiddleware];
  const enhancer =
    process.env.NODE_ENV === "production"
      ? compose(applyMiddleware(...middlewares))
      : composeWithDevTools(applyMiddleware(...middlewares));
  const store = createStore(reducer, enhancer);
  store.sagaTask = sagaMiddleware.run(rootSaga);
  return store;
}

const wrapper = createWrapper(configureStore, {
  debug: process.env.NODE_ENV === "development",
});

export default wrapper;

 

답변 1

0

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

post를 선언 안 했는데 post를 쓰셨으니 에러가 발생하죠. DeskLatestPost 두 번째를 봐보세요.

박지연님의 프로필 이미지
박지연
질문자

헉 죄송합니다 정작 묻고싶은걸 질문하지못했습니다..

그 바로 윗줄에 있는 코드인

{mainPosts.map((post) => (
        <DeskLatestPost post={post} />
      ))}

이 부분이 아예 안떠서 컴포넌트는 잘뜨는지 확인하려고 두번째 코드를 넣은건데

다른부분이 잘못되었나 싶어서요 ㅜㅜ..

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

mainPosts가 []였을 겁니다. 리덕스 데브툴즈에서 mainPosts 값을 확인해보세요.

박지연님의 프로필 이미지
박지연
질문자

네 정말 비어있어요!

그러면 reducer쪽이 문제일까요..?

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

제가 궁금한 것은 mainPosts 불러오는 액션을 어디서 디스패치하셨나요?

박지연님의 프로필 이미지
박지연
질문자

posts/index.js에 인피니티 스크롤링 코드 내부에 작성하였는데

작업이 중지되는 것 같습니다.

image

image

function Home() {
  const dispatch = useDispatch();
  const { me } = useSelector((state) => state.user);
  const { mainPosts, hasMorePosts, loadPostsLoading } = useSelector(
    (state) => state.post
  );

  // 인피니티 스크롤링 코드
  const [ref, inView] = useInView();
  useEffect(() => {
    if (inView && hasMorePosts && !loadPostsLoading) {
      const lastId = mainPosts[mainPosts.length - 1]?.id;
      dispatch({
        type: LOAD_POSTS_REQUEST,
        lastId,
      });
    }
  }, [inView, hasMorePosts, loadPostsLoading, mainPosts]);

  return (
    <>
      <Header />
      <Nav />
    
      <ChoiceAddress />
      <DeskMainMiddle />
     
      {mainPosts.map((post) => (
        <DeskLatestPost key={post.id} post={post} />
      ))}
      <div
        ref={hasMorePosts && !loadPostsLoading ? ref : undefined}
        style={{ height: 10 }}
      />
      <Footer />
    </>
  );
}

export default Home;

saga의 post.js인데 에러발생해서 catch문으로 넘어갔는데

컨솔까지만뜨고 LOAD_POSTS_FAILURE도 실행이 안되는 것 같습니다..

function* loadPosts(action) {
  try {
    // const result = yield call(loadPostsAPI, action.data);
    yield delay(1000);
    yield put({
      type: LOAD_POSTS_SUCCESS,
      data: generateDummyPost(10),
    });
  } catch (err) {
    console.error(err);
    yield put({
      type: LOAD_POSTS_FAILURE,
      data: err.response.data,
    });
  }
}
제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

에러메시지에 generateDummyPost가 문제라고 되어있네요. 에러메시지를 보세요. faker 라이브러리 몇 버전 사용 증이신가요?

박지연님의 프로필 이미지
박지연
질문자

    "@faker-js/faker": "^7.5.0",

위 버전 사용중입니다

박지연님의 프로필 이미지
박지연
질문자

    "@faker-js/faker": "^6.3.1",

버전 깃에 있는 버전으로 사용하니까 고쳐졌습니다..! 감사합니다

박지연님의 프로필 이미지
박지연

작성한 질문수

질문하기