inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

saga 쪼개고 reducer와 연결하기

toolkit, saga를 사용하는데 saga에서 로그인정보 받을때 state가 이전 state가 아니라 proxy데이터가 나옵니다.

283

챠챠_

작성한 질문수 40

0

안녕하세요 제로초님

toolkit, saga를 사용하는데 saga에서 로그인정보 받을때 state가 이전 state가 아니라 proxy데이터가 나옵니다.

 

saga에서 이런식으로 호출을 해주면

action 데이터도 잘 찍힙니다.

function* login(action) {
	try {
		console.log("saga login");
		console.log(action);
		// const result = yield call(loginAPI, action.data);
		yield delay(1000);
		yield put({
			type: loginSuccessAction,
			payload: action.payload,
		});
	} catch (err) {
		yield put({
			type: loginFailureAction,
			// data: err.response.data,
		});
	}
}

그다음 리듀서에서
const userSlice = createSlice({ name: "user", initialState, reducers: { logIn: (state, action) => { state.isLoggedIn = true; state.me = action.payload; }, logOut: (state) => { state.isLoggedIn = false; state.me = null; }, loginRequestAction: (state) => { console.log("state", state); state.isLoggingIn = true; }, loginSuccessAction: (state, action) => { console.log("reducer login"); console.log("state", state); state.isLoggingIn = false; state.isLoggedIn = false; state.me = action.payload; state.me.nickname = "zzimzzim"; }, loginFailureAction: (state) => { state.isLoggingIn = false; state.isLoggedIn = false; }, logoutRequestAction: (state) => { state.isLoggingOut = true; }, logoutSuccessAction: (state) => { state.isLoggingOut = false; state.isLoggedIn = false; state.me = null; }, logoutFailureAction: (state) => { state.isLoggingOut = false; }, }, extraReducers: (builder) => builder .addCase(HYDRATE, (state, action) => ({ ...state, ...action.payload.user, })) .addDefaultCase((state) => state), });

 

위와같이 코드를 만들고

로그인을 해보면

action으로 로그인 정보를 잘 내려줍니다.

원래는 이전의 state (현 store데이터)를 받아오고

거기서 action데이터를 넣어서 업데이트해줘야하는데,

state에서 proxy데이터가 내려와서 업데이트가 안되고 있습니다. ㅠ

 

리듀서에서 action 데이터 받고, state호출했을때,

  1. Proxy(Object) {type_: 0, scope_: {…}, modified_: false, finalized_: false, assigned_: {…}, …}

    1. [[Handler]]: null

    2. [[Target]]: null

    3. [[IsRevoked]]: true

이러한 경우에 reducer에서 state를 받아오는 방법이 있을까요? 혹시 코드가 이상하거나 틀렸다면 지적해주시면 감사하겠습니다.

react redux node.js express next.js

답변 2

0

제로초(조현영)

코드 포매팅좀 해주세요. 툴킷을 쓸 때는 프록시 객체가 나오는 게 맞습니다.

0

챠챠_

/sagas/user.js

import { all, fork, delay, put, takeLatest } from "redux-saga/effects";
import axios from "axios";
import {
	loginRequestAction,
	loginFailureAction,
	loginSuccessAction,
	logoutFailureAction,
	logoutRequestAction,
	logoutSuccessAction,
} from "../reducers/user";

function loginAPI(data) {
	return axios.post("/api/login", data);
}

function* login(action) {
	try {
		yield delay(1000);
		yield put(loginSuccessAction(action.payload));
	} catch (err) {
		yield put({
			type: loginFailureAction,
			// data: err.response.data,
		});
	}
}

function logoutAPI() {
	return axios.post("/api/logout");
}

function* logout() {
	try {
		// const result = yield call(logoutAPI);
		yield delay(1000);
		yield put({
			type: logoutSuccessAction,
			// data: result.data,
		});
	} catch (err) {
		yield put({
			type: logoutFailureAction,
			data: err.response.data,
		});
	}
}

function* watchLogIn() {
	yield takeLatest(loginRequestAction, login);
}

function* watchLogOut() {
	yield takeLatest(logoutRequestAction, logout);
}

export default function* userSaga() {
	yield all([fork(watchLogIn), fork(watchLogOut)]);
}

 

/reducers/user.js

import { createSlice, current } from "@reduxjs/toolkit";
import { HYDRATE } from "next-redux-wrapper";

const initialState = {
	isLoggingIn: false, // 로그인 시도중
	isLoggingOut: false, // 로그아웃 시도중
	isLoggedIn: false,
	me: null,
	signUpData: {},
	loginData: {},
};

const userSlice = createSlice({
	name: "user",
	initialState,
	reducers: {
		logIn: (state, action) => {
			state.isLoggedIn = true;
			state.me = action.payload;
		},
		logOut: (state) => {
			state.isLoggedIn = false;
			state.me = null;
		},
		loginRequestAction: (state) => {
			// console.log("reducer loginRequestAction");
			// console.log("state", state);
			state.isLoggingIn = true;
		},
		loginSuccessAction: (state, action) => {
			console.log("reducer login");
			console.log("state", state);
			
			console.log(action);

			state.isLoggingIn = false;
			state.isLoggedIn = true;
			state.me = action.payload;
			state.me.nickname = "zzimzzim";
		},
		loginFailureAction: (state) => {
			state.isLoggingIn = false;
			state.isLoggedIn = false;
		},
		logoutRequestAction: (state) => {
			state.isLoggingOut = true;
		},
		logoutSuccessAction: (state) => {
			state.isLoggingOut = false;
			state.isLoggedIn = false;
			state.me = null;
		},
		logoutFailureAction: (state) => {
			state.isLoggingOut = false;
		},
	},
	extraReducers: (builder) =>
		builder
			.addCase(HYDRATE, (state, action) => ({
				...state,
				...action.payload.user,
			}))
			.addDefaultCase((state) => state),
}); 

export const {
	logIn,
	logOut,
	loginRequestAction,
	loginSuccessAction,
	loginFailureAction,
	logoutRequestAction,
	logoutSuccessAction,
	logoutFailureAction,
} = userSlice.actions; // 액션 생성 함수

export default userSlice.reducer; // 리듀서

로그인할 때

const onFinish = useCallback((data) => {
		dispatch(loginRequestAction({ id: data.userId, password: data.password }));
	}, []);

주 코드는 위와 같습니다!

0

챠챠_

아.. 이상하네요 어제 몇번이나 시도했었는데

데이터를 못받아오더니 컴터 껐다키고 다른거하다가 다시 테스트해보니까 function* login(action)

{
	try {
		console.log("saga login---------------------------------");
		console.log("action", action);
		// const result = yield call(loginAPI, action.data);
		yield delay(1000);
		yield put({
			type: loginSuccessAction,
			payload: action.payload,
		});
	} catch (err) {
		yield put({
			type: loginFailureAction,
			// data: err.response.data,
		});
	}
}

이렇게 해도 데이터를 잘 받고,

로그인도 잘 됩니다.

귀신이곡할노릇이군요...

제가 무엇을 잘못했을텐데 그걸 몰라 답답한데 그래도 잘 되서 다행입니다. 감사합니다.!

0

제로초(조현영)

put type에 action함수 자체를 넣어도 되는건 처음보네요. saga put이 지원하는 특수기능일지도 모르겠습니다.

0

챠챠_

껐다 켰다 검색해보니function* login(action) { try { // console.log("saga login"); // console.log(action); // const result = yield call(loginAPI, action.data); yield delay(1000); yield put(loginSuccessAction(action.payload)); } catch (err) { yield put({ type: loginFailureAction, // data: err.response.data, }); } }

이런식으로

호출해주면 잘 되는것 같습니다.
loginSuccessAction(action.payload)

reducer에서는 데이터 받을때 proxy로 보여도 되는것 같습니다.

후 쉽지않네요. 혹시나 틀렸거나 수정할거있으면 알려주시면 감사하겠습니다 ; D

넥스트 버젼 질문

0

78

2

로그인시 401 Unauthorized 오류가 뜹니다

0

89

1

무한 스크롤 중 스크롤 튐 현상

0

175

1

특정 페이지 접근을 막고 싶을 때

0

103

2

createGlobalStyle의 위치와 영향범위

0

96

2

인라인 스타일 리렌더링 관련

0

91

2

vsc 에서 npm init 설치시 오류

0

146

2

nextjs 15버전 사용 가능할까요?

0

158

1

화면 새로고침 문의

0

121

1

RTK에서 draft, state 차이가 있나요?

0

153

2

Next 14 사용해도 될까요?

0

452

1

next, node 버전 / 폴더 구조 질문 드립니다.

0

349

1

url 오류 질문있습니다

0

211

1

ssh xxxxx로 우분투에 들어가려니까 port 22: Connection timed out

0

373

1

sudo certbot --nginx 에러

0

1275

2

Minified React error 콘솔에러 (hydrate)

0

470

1

카카오 공유했을 때 이전에 작성했던 글이 나오는 버그

0

247

1

프론트서버 배포 후 EADDRINUSE에러 발생

0

327

1

npm run build 에러

0

518

1

front 서버 npm run build 중에 발생한 에러들

0

381

1

서버 실행하고 브라우저로 들어갔을때 404에러

0

338

2

css 서버사이드 랜더링이 적용되지 않아서 문의 드립니다.

0

288

1

팔로워 3명씩 불러오고 데이터 합쳐주는걸로 바꾸고 서버요청을 무한으로하고있습니다.

0

239

2

해시태그 검색에서 throttle에 관해 질문있습니다.

0

201

1