• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    미해결

서버 사이드랜더링 후 오류 관련 질문 드립니다.

22.09.22 23:10 작성 조회수 287

0

Server Error

Error: Error serializing .initialState.user.loadMyInfoErr returned from getServerSideProps in "/". Reason: undefined cannot be serialized as JSON. Please use null or omit this value all together.


선생님 해당 애러 한시간 넘게 지금 찾고있는데 일단 번역해보거나 지금 다른분이 올리셨던 질문이 똑같은게 있었는데 도움이 되질않았습니다. 보니 직렬화 문제? 그리고 initialState.user.loadMyInfoErr이쪽이 문제였던것같아 리듀서에 loadMyInfoerr를 그냥 없애보니 화면랜더링은 되는데 로그인이 안되는 게 발생했습니다. 일단 선생님께 질문드리고 난뒤에도 계속 찾아보겠습니다.

//index.js

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { END } from 'redux-saga'
import AppLayout from '../components/AppLayout'
import PostForm from '../components/PostForm'
import PostCard from '../components/PostCard'
import { LOAD_POSTS_REQUEST } from '../reducers/post'
import { LOAD_MYINFO_REQUEST } from '../reducers/user'
import wrapper from '../store/configureStore'
import axios from 'axios'

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

  useEffect(() => {
    if (retweetErr) {
      alert(retweetErr)
    }
  }, [retweetErr])

  useEffect(() => {
    function onScroll() {
      if (window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300) {
        if (hasMorePosts && !loadPostsLoading) {
          const lastId = mainPosts[mainPosts.length - 1]?.id;
          dispatch({
            type: LOAD_POSTS_REQUEST,
            lastId,
          });
        }
      }
    }
    window.addEventListener('scroll', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
    };
  }, [hasMorePosts, loadPostsLoading, mainPosts])

  return (
    <AppLayout>
      {me && <PostForm />}
      {mainPosts.map((item) => <PostCard key={item.id} post={item} />)}
    </AppLayout>
  )
}

export const getServerSideProps = wrapper.getServerSideProps( async (context) => {
  context.store.dispatch({
    type: LOAD_MYINFO_REQUEST,
  });
  context.store.dispatch({
    type: LOAD_POSTS_REQUEST,
  });
  context.store.dispatch(END);
  await context.store.sagaTask.toPromise();
})
export default Homeimport { delay, all, fork, put, takeLatest, call } from "redux-saga/effects";
import axios from 'axios'
import {
    LOG_IN_REQUEST,
    LOG_IN_SUCCESS,
    LOG_IN_FAILURE,
    LOG_OUT_REQUEST,
    LOG_OUT_SUCCESS,
    LOG_OUT_FAILURE,
    SIGN_UP_REQUEST,
    SIGN_UP_SUCCESS,
    SIGN_UP_FAILURE,
    FOLLOW_REQUEST,
    FOLLOW_SUCCESS,
    FOLLOW_FAILURE,
    UNFOLLOW_REQUEST,
    UNFOLLOW_SUCCESS,
    UNFOLLOW_FAILURE,
    LOAD_USER_REQUEST,
    LOAD_USER_SUCCESSS,
    LOAD_USER_FAILURE,
    CHANGE_NICK_REQUEST,
    CHANGE_NICK_SUCCESS,
    CHANGE_NICK_FAILURE,
    LOAD_FOLLOWER_REQUEST,
    LOAD_FOLLOWER_SUCCESS,
    LOAD_FOLLOWER_FAILURE,
    LOAD_FOLLWING_REQUEST,
    LOAD_FOLLWING_SUCESSS,
    LOAD_FOLLWING_FAILURE,
    REMOVE_FOLLOWER_REQUEST,
    REMOVE_FOLLOWER_SUCCESS,
    REMOVE_FOLLOWER_FAILURE,
    LOAD_MYINFO_REQUEST,
    LOAD_MYINFO_SUCCESSS,
    LOAD_MYINFO_FAILURE
} from '../reducers/user'

function loadMyInfoAPI() {
    return axios.get('/user')
}

function* loadMyInfo() {
    try {
        const result = yield call(loadMyInfoAPI)
        yield put({
            type: LOAD_MYINFO_SUCCESSS,
            data: result.data,
        });
    } catch (err) {
        console.log(err);
        yield put({
            type: LOAD_MYINFO_FAILURE,
            error: err.response.data
        });
    }
}


function getUserAPI(data) {
    return axios.get(`/user/${data}`)
}

function* getUser(action) {
    try {
        const result = yield call(getUserAPI, action.data)
        yield put({
            type: LOAD_USER_SUCCESSS,
            data: result.data,
        });
    } catch (err) {
        yield put({
            type: LOAD_USER_FAILURE,
            error: err.response.data
        });
    }
}

function getFollwerAPI(data) {
    return axios.get('/user/follower', data)
}

function* getFollwer(action) {
    try {
        const result = yield call(getFollwerAPI, action.data)
        yield put({
            type: LOAD_FOLLOWER_SUCCESS,
            data: result.data,
        });
    } catch (err) {
        yield put({
            type: LOAD_FOLLOWER_FAILURE,
            error: err.response.data
        });
    }
}

function getFollowingAPI(data) {
    return axios.get('/user/following', data)
}

function* getFollowing(action) {
    try {
        const result = yield call(getFollowingAPI, action.data)
        yield put({
            type: LOAD_FOLLWING_SUCESSS,
            data: result.data,
        });
    } catch (err) {
        yield put({
            type: LOAD_FOLLWING_FAILURE,
            error: err.response.data
        });
    }
}


function logInAPI(data) {
    return axios.post('/user/login', data)
}

function* logIn(action) {
    try {
        const result = yield call(logInAPI, action.data)
        yield put({
            type: LOG_IN_SUCCESS,
            data: result.data,
        });
    } catch (err) {
        yield put({
            type: LOG_IN_FAILURE,
            error: err.response.data
        });
    }
}

function logOutAPI() {
    return axios.post('/user/logout');
}

function* logOut() {
    try {
        yield call(logOutAPI);
        yield put({
            type: LOG_OUT_SUCCESS,
        });
    } catch (err) {
        console.error(err);
        yield put({
            type: LOG_OUT_FAILURE,
            error: err.response.data,
        });
    }
}



function signUpAPI(data) {
    return axios.post('/user', data)
}

function* signUp(action) {
    try {
        const result = yield call(signUpAPI, action.data);
        console.log(result);
        yield put({
            type: SIGN_UP_SUCCESS,
        });
    } catch (err) {
        console.error(err);
        yield put({
            type: SIGN_UP_FAILURE,
            error: err.response.data,
        });
    }
}
function followAPI(data) {
    return axios.patch(`/user/${data}/follow`)
}

function* follow(action) {
    try {
        const result = yield call(followAPI , action.data)
        yield put({
            type: FOLLOW_SUCCESS,
            data: result.data
        });
    } catch (err) {
        yield put({
            type: FOLLOW_FAILURE,
            error: err.response.data
        });
    }
}

function unFollowAPI(data) {
    return axios.delete(`/user/${data}/follow`)
}

function* unFollow(action) {
    try {
        const result = yield call(unFollowAPI, action.data)
        yield console.log(result)
        yield put({
            type: UNFOLLOW_SUCCESS,
            data: result.data
        });
    } catch (err) {
        yield put({
            type: UNFOLLOW_FAILURE,
            error: err.response.data
        });
    }
}

function chanegeNickAPI(data) {
    return axios.patch('/user/nickname', { nickname : data })
}

function* chanegeNick(action) {
    try {
        const result = yield call(chanegeNickAPI, action.data)
        yield console.log(result)
        yield put({
            type: CHANGE_NICK_SUCCESS,
            data: result.data,
        });
    } catch (err) {
        yield put({
            type: CHANGE_NICK_FAILURE,
            error: err.response.data
        });
    }
}

function removeFollowerAPI(data) {
    return axios.delete(`/user/${data}/following`)
}

function* removeFollower(action) {
    try {
        const result = yield call(removeFollowerAPI, action.data)
        console.log(result)
        yield console.log(result)
        yield put({
            type: REMOVE_FOLLOWER_SUCCESS,
            data: result.data,
        });
    } catch (err) {
        yield put({
            type: REMOVE_FOLLOWER_FAILURE,
            error: err.response.data
        });
    }
}

function* watchLogIn() {
    yield takeLatest(LOG_IN_REQUEST, logIn)
}

function* watchLogOut() {
    yield takeLatest(LOG_OUT_REQUEST, logOut)
}

function* watchSignUp() {
    yield takeLatest(SIGN_UP_REQUEST, signUp)
}

function* watchFollow() {
    yield takeLatest(FOLLOW_REQUEST, follow)
}

function* watchUnFollow() {
    yield takeLatest(UNFOLLOW_REQUEST, unFollow)
}

function* watchGetUser() {
    yield takeLatest(LOAD_USER_REQUEST, getUser)
}

function* watchGetFollow() {
    yield takeLatest(LOAD_FOLLOWER_REQUEST, getFollwer)
}

function* watchGetFollowing() {
    yield takeLatest(LOAD_FOLLWING_REQUEST, getFollowing)
}

function* watchChanegeNick() {
    yield takeLatest(CHANGE_NICK_REQUEST, chanegeNick)
}

function* watchRemoveFollower(){
    yield takeLatest(REMOVE_FOLLOWER_REQUEST, removeFollower)
}

function* watchLoadMyInfo(){
    yield takeLatest(LOAD_MYINFO_REQUEST, loadMyInfo)
}

export default function* userSaga() {
    yield all([
        fork(watchLogIn),
        fork(watchLoadMyInfo),
        fork(watchLogOut),
        fork(watchLogOut),
        fork(watchSignUp),
        fork(watchFollow),
        fork(watchUnFollow),
        fork(watchRemoveFollower),
        fork(watchGetUser),
        fork(watchChanegeNick),
        fork(watchGetFollow),
        fork(watchGetFollowing),
    ])
}
const express = require('express')
const bcrypt = require('bcrypt')
const { User, Post, Image, Comment } = require('../models')
const { isLoggedIn, isNotLoggedIn } = require('./middlewares')
const passport = require('passport');
const db = require('../models');

const router = express.Router();

router.get('/', async (req, res, next) => { // GET /user
    try {
        if (req.user) {
            const fullUserWithoutPassword = await User.findOne({
                where: { id: req.user.id },
                attributes: {
                    exclude: ['password']
                },
                include: [{
                    model: Post,
                    attributes: ['id'],
                }, {
                    model: User,
                    as: 'Followings',
                    attributes: ['id'],
                }, {
                    model: User,
                    as: 'Followers',
                    attributes: ['id'],
                }]
            })
            res.status(200).json(fullUserWithoutPassword);
        } else {
            res.status(200).json(null);
        }
    } catch (error) {
        console.error(error);
        next(error);
    }
});

router.post('/login', isNotLoggedIn, (req, res, next) => {
    passport.authenticate('local', (err, user, info) => {
        if (err) {
            console.error(err)
            return next(err)
        }
        if (info) {
            return res.status(401).send(info.reason);
        }
        return req.login(user, async (loginErr) => {
            if (loginErr) {
                console.error(loginErr)
                return next(loginErr)
            }
            const fullUserWithoutPassword = await User.findOne({
                where: { id: user.id },
                attributes: {
                    exclude: ['password']
                },
                include: [{
                    model: Post,
                }, {
                    model: User,
                    as: 'Followings',
                }, {
                    model: User,
                    as: 'Followers',
                }]
            })
            return res.status(200).json(fullUserWithoutPassword)
        })
    })(req, res, next)
})

router.post('/logout', isLoggedIn, (req, res) => {
    req.logout();
    req.session.destroy();
    res.send('OK')
})

router.post('/', isNotLoggedIn, async (req, res, next) => {
    try {
        const exUser = await User.findOne({
            where: {
                email: req.body.email,
            }
        });
        if (exUser) {
            return res.status(403).send('이미 사용 중인 아이디입니다.');
        }
        const hashedPassword = await bcrypt.hash(req.body.password, 12);
        await User.create({
            email: req.body.email,
            nickname: req.body.nick,
            password: hashedPassword,
        });
        res.status(201).send('ok');
    } catch (error) {
        console.error(error);
        next(error); // status 500
    }
})

router.patch('/nickname', isLoggedIn, async (req, res, next) => {
    try {
        console.log(req.body)
        await User.update({
            nickname: req.body.nickname
        }, {
            where: { id: req.user.id }
        })
        res.status(200).json({ nickname: req.body.nickname })
    } catch (error) {
        console.log(error)
        next(error)
    }
})

router.patch('/:userId/follow', isLoggedIn, async (req, res, next) => { // 유저 팔로우
    try {
        const user = await User.findOne({ where: { id: req.params.userId } }) // 게시글 작성자 1번
        if (!user) {
            res.status(403).send('없는 유저입니다.')
        }
        await user.addFollowers(req.user.id); // 게시글 작성자를 팔로우한다 / 내 계정 정보를 넘김 // 팔로워 아이디 2번
        res.status(200).json({ userId: parseInt(req.params.userId, 10) })
    } catch (error) {
        console.log(error)
        next(error)
    }
})

router.delete('/:userId/follow', isLoggedIn, async (req, res, next) => { // 유저 팔로우 취소
    try {
        const user = await User.findOne({ where: { id: req.params.userId } })
        if (!user) {
            res.status(403).send('없는 유저입니다.')
        }
        await user.removeFollowers(req.user.id);
        res.status(200).json({ userId: parseInt(req.params.userId, 10) })
    } catch (error) {
        console.log(error)
        next(error)
    }
})

router.delete('/:userId/following', isLoggedIn, async (req, res, next) => { // 유저 팔로우 취소
    try {
        const user = await User.findOne({ where: { id: req.params.userId } })
        if (!user) {
            res.status(403).send('없는 유저입니다.')
        }
        await user.removeFollowings(req.user.id);
        res.status(200).json({ userId: parseInt(req.params.userId, 10) })
    } catch (error) {
        console.log(error)
        next(error)
    }
})

router.get('/follower', isLoggedIn, async (req, res, next) => {
    try {
        const user = await User.findOne({ where: { id: req.user.id } })
        if (!user) {
            res.status(403).send('없는 유저입니다.')
        }
        const followers = await user.getFollowers();
        res.status(200).json(followers)
    } catch (error) {
        console.log(error)
        next(error)
    }
})

router.get('/following', isLoggedIn, async (req, res, next) => {
    try {
        const user = await User.findOne({ where: { id: req.user.id } })
        if (!user) {
            res.status(403).send('없는 유저입니다.')
        }
        const followings = await user.getFollowings();
        res.status(200).json(followings)
    } catch (error) {
        console.log(error)
        next(error)
    }
})

module.exports = router;

답변 1

답변을 작성해보세요.

2

uphoon님의 프로필

uphoon

질문자

2022.09.22

아 선생님 해결했습니다! reudcer에서 swich문에 case끝날때 break 안해줘서 오류 발생했던것 같습니다 . 감사합니다!!