• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    미해결

full reload 될때는 서버 데이터를 호출하는데 그 이후로 새로고침할대는 호출하지 않아서 답답합니다

24.05.06 14:07 작성 조회수 118

0

안녕하세요 제로초님

full reload 될때는 서버 데이터를 호출하는데 그 이후로 새로고침할대는 호출하지 않아서 답답합니다.

구글링하고 제로초님 로직을 따라 만들어보다가

posts게시물이 내려오도록 수정을 했는데,

이상하게 처음엔 서버에 요청하고 데이터를 내려받아서 게시물이 보이는데,

그이후 새로고침하면 서버 호출까지도 안하는것 같습니다.

이젠 좀 나오나 싶었는데, full reload될때만 되서 여유되실 때 로직한번 봐주시면 감사하겠습니다 ㅠ

/ pages/index.js

import { useDispatch, useSelector } from "react-redux";
import AppLayout from "../components/AppLayout";
import PostForm from "../components/PostForm";
import PostCard from "../components/PostCard";
import { useEffect } from "react";
import { loadPostsRequestAction } from "../reducers/post";
import { loadMyInfoRequestAction } from "../reducers/user";
import wrapper from "../store/configurStore";
import axios from "axios";
import { END } from "redux-saga";

// 프론트, 브라우저 같이 실행
const Home = () => {
	const { me } = useSelector((state) => state.user);
	const { mainPosts, hasMorePosts, loadPostsLoading, retweetError } = useSelector((state) => state.post);
	const dispatch = useDispatch();

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

	useEffect(() => {
		const onScroll = () => {
			if (window.scrollY + document.documentElement.clientHeight > document.documentElement.scrollHeight - 300) {
				if (hasMorePosts && !loadPostsLoading) {
					const lastId = mainPosts[mainPosts.length - 1]?.id;
					dispatch(loadPostsRequestAction({ lastId, limit: 10 }));
				}
			}
		};

		window.addEventListener("scroll", onScroll);
		return () => {
			window.removeEventListener("scroll", onScroll);
		};
	}, [hasMorePosts, loadPostsLoading, mainPosts]);

	return (
		<AppLayout>
			{me && <PostForm />}

			{/* 순서가 바뀌거나 삭제될 수 있는 리스트들에 key값으로 index를 쓰면 안됀다. */}
			{/* 반복문이 있고 바뀌지 않는 리스트일 경우에만 사용해도 된다. */}
			{mainPosts.map((post) => (
				<PostCard key={post.id} post={post} />
			))}
		</AppLayout>
	);
};

export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => {

	store.dispatch(loadPostsRequestAction());
	store.dispatch(loadMyInfoRequestAction());
	store.dispatch(END);
	await store.sagaTask.toPromise(); // 사가 작업 완료 대기
	console.log("state", store.getState());
});

export function reportWebVitals(metric) {
	console.log(metric);
}

export default Home;


/pages/_app.js

import PropTypes from "prop-types";
import Head from "next/head";
import { Provider } from "react-redux";
import wrapper from "../store/configurStore";

const NodeBird = ({ Component, ...rest }) => {
	const { store, props } = wrapper.useWrappedStore(rest);
	const { pageProps } = props;
	return (
		<Provider store={store}>
			<Head>
				<meta charSet='utf-8' />
				<meta
					name='viewport'
					content='width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'
				/>
				<title>NodeBird</title>
			</Head>
			<Component {...pageProps} />
		</Provider>
	);
};

NodeBird.propTypes = {
	Component: PropTypes.elementType.isRequired,
	pageProps: PropTypes.any.isRequired,
};

export function reportWebVitals(metric) {
	// console.log("-----------------------------------");
	// console.log(metric);
}

export default NodeBird;

 

store/configureStore.js

import { createWrapper } from "next-redux-wrapper";
import { configureStore } from "@reduxjs/toolkit";
import reducer from "../reducers";
import user from "../reducers/user";
import post from "../reducers/post";
import createSagaMiddleware from "redux-saga";
import rootSaga from "../sagas";

// redux-thunk를 참조해서 만든 미들웨어
const loggerMiddleware =
	({ dispatch, getState }) =>
	(next) =>
	(action) => {
		return next(action);
	};

const sagaMiddleware = createSagaMiddleware();

function getServerState() {
	return typeof document !== "undefined" ? JSON.parse(document.querySelector("#__NEXT_DATA__").textContent)?.props.pageProps.initialState : undefined;
}
const serverState = getServerState();
const makeStore = () => {
	// configureStore: store 를 생성
	const store = configureStore({
		reducer: {
			user,
			post,
		}, 
		middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat([sagaMiddleware, loggerMiddleware]),
		preloadedState: serverState, // SSR
	});

	store.sagaTask = sagaMiddleware.run(rootSaga);
	return store;
};

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

export default wrapper;

 

/reducers.js/post.js

 

import { HYDRATE } from "next-redux-wrapper";
import { createSlice } from "@reduxjs/toolkit";
import shortId from "shortid";
import produce from "immer";

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,
	likePostLoading: false, // 좋아요 시도중
	likePostDone: false,
	likePostError: null,
	unLikePostLoading: false, // 좋아요 취소중
	unLikePostDone: false,
	unLikePostError: null,
	uploadImagesLoading: false, // 이미지 업로드 시도중
	uploadImagesDone: false,
	uploadImagesError: null,
	retweetLoading: false, // 리트윗 시도중
	retweetDone: false,
	retweetError: null,
};


const postSlice = createSlice({
	name: "post",
	initialState,
	reducers: {loadPostsRequestAction: (state, action) => {
			console.log("-------------------요청-------------------");
			state.loadPostsLoading = true;
			state.loadPostsDone = false;
			state.loadPostsError = null;
		},
		loadPostsSuccessAction: (state, action) => {
			console.log("-------------------성공-------------------");

			state.loadPostsLoading = false;
			state.loadPostsDone = true;
			state.mainPosts = [...
			state.hasMorePosts = action.payload.length === 10;

		},
		loadPostsFailureAction: (state, action) => {
			console.log("-------------------실패-------------------");
			state.loadPostsLoading = false;
			state.loadPostsError = action.payload;
		},
	},
	extraReducers: (builder) =>
		builder
			.addCase(HYDRATE, (state, action) => {
				console.log("HYDRATE", action);
				return {
					...state,
					...action.payload.post,
				};
			})
			.addDefaultCase((state) => state),
});

export const {
	loadPostsRequestAction,
	loadPostsSuccessAction,
	loadPostsFailureAction,

} = postSlice.actions;
export default postSlice.reducer;

 

 

답변 2

·

답변을 작성해보세요.

0

혹시 새로고침 시 브라우저에서 바로 캐싱된 데이터가 내려온 거 아닌가요? 개발자도구에서 disable cache 클릭한 상태로 새로고침 해보세요.

챠챠_님의 프로필

챠챠_

질문자

2024.05.06

disable cache 해봤는데도 동일하게 증상이 나와서

어제오늘 답답해서 saga에서 깃헙에 올려주신것처럼 thunk로 수정해서 다시 해보려고 합니다 ㅠ ㅎㅎㅎ답벼 ㄴ감사합니다!

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.05.06

안녕하세요, 인프런 AI 인턴입니다. 챠챠_ 님의 질문에 관하여 유사한 상황을 다룬 내용이 있어 이를 소개해 드리겠습니다. 질문하신 내용은 새로고침할 때 서버 요청이 실행되지 않는 문제와 관련이 있습니다.

초기 로드 시 서버로부터 데이터를 잘 받아온 후, 새로고침할 때 요청이 전송되지 않는 문제는 클라이언트 사이드에서의 상태 관리 또는 서버 사이드 렌더링 로직에 문제가 있을 수 있습니다. 여기서 주목할 점은 getServerSideProps 함수가 정상적으로 작동하지 않거나, 클라이언트 사이드에서 추가 로드(스크롤 이벤트 등)를 처리하는 로직에 이슈가 있을 가능성이 있습니다.

유사한 질문 및 답변

  1. getServerSideProps에서 데이터가 제대로 내려오지 않는듯합니다.

    • 해당 질문에서는 getServerSideProps를 사용할 때 데이터가 제대로 내려오지 않는 상황을 다루고 있습니다. 이와 유사하게 질문자님의 경우에도 새로고침 시 데이터 호출이 제대로 이루어지지 않는 상황으로 볼 수 있습니다. getServerSideProps 내에서 실행되는 로직을 재확인하고, 서버 상태와 리덕스 스토어가 올바르게 연동되어 있는지 검토하는 것이 좋습니다.

질문자님의 경우, 서버에서 데이터를 받아오는 과정과 이를 클라이언트 상태로 관리하는 과정에 이슈가 있을 수 있음을 시사합니다. getServerSideProps 내부에서 데이터를 불러온 후 상태에 반영하는 부분과, 해당 상태를 클라이언트 사이드에서 활용하는 로직을 세밀하게 검토해보시는 것이 중요합니다.

또한, Redux Saga를 사용하여 비동기 액션을 관리하는 경우, 해당 액션들이 getServerSideProps와 호환되어 올바르게 실행되는지 확인해야 합니다. 서버로부터 데이터를 성공적으로 불러온 후, 이를 리덕스 스토어의 상태로 올바르게 반영하는지 점검해 보시기 바랍니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏

추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.