728x90
useReducer를 사용하면, dispatch 후, 로직 순서 보장이 안 된다.
그 이유.
useReducer는 기본적으로 '비동기 로직'을 포함하는 '비동기 액션'을 dispatch 하지 않아요.
개요
context를 사용해서,
app.tsx에 authContext를 추가했다.
auth.tsx에 context관련 코드는 넣었다.
auth.tsx에서 export로 useStateContext와 useDispatchContext란 이름으로 UI컴포넌트에서 import할 수 있게끔했다.
로그인을 요청 후, 서버로부터 유저 정보를 응답받고, 유저 정보를 context에 저장시키려고 했다.
context에서는 useRouter를 사용했다.
하지만, 코드가 실행되는 타임라인은 다음과 같았다.
1. '로그인' 버튼 클릭
2. 서버로 로그인 요청 및 응답 받음
3. 응답을 context dispatch한다.
코드로 보면,
로그인 UI 컴포넌트 pages/login.tsx
// 로그인 요청
const handleLogin = async (e: FormEvent) => {
e.preventDefault();
try {
const res = await submitLogin({ username, password });
console.log("전", context); 👈 실제 동작 순서 1
await dispatch("LOGIN", res.data.user);
console.log("후", context); 👈 실제 동작 순서 2
} catch (err: any) {
console.error(err);
}
context/auth.tsx
reducer가 있고, reducer를 사용하는 useReducer훅이 있다.
const reducer = (state: State, { type, payload }: Action) => {
switch (type) {
case "LOGIN":
console.log("로그인"); 👈 실제 동작 순서 3
return {
...state,
authenticated: true,
user: payload,
};
// ...
default: ...
}
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [state, defaultDispatch] = useReducer(reducer, {
user: null,
authenticated: false,
isLoading: true,
});
console.log(state); 👈 실제 동작 순서 4
const dispatch = (type: string, payload?: any) => {
defaultDispatch({ type, payload });
};
return (
<DispatchContext.Provider value={dispatch}>
<StateContext.Provider value={state}>{children}</StateContext.Provider>
</DispatchContext.Provider>
);
};
브라우저 동작 콘솔
보세요.
콘솔 '전', '후'의 사이에는 dispatch가 있는데, 콘솔이 찍힌 다음에서 dispatch가 실행되고 있죠?
728x90
'React' 카테고리의 다른 글
[Redux-saga]왜 그냥 제너레이터만 안 쓰고, 사가로 제너레이터 처리를 해야하는가? (0) | 2022.11.07 |
---|---|
[Redux + Redux saga] 리덕스와 리덕스 사가는 뭔가? 왜 쓰는가? (0) | 2022.11.02 |
[testing-library] 인풋필트 빈 값으로 만들기 (0) | 2022.10.29 |
[React] 모르는 것 (0) | 2022.10.14 |
[redux] redux는 비동기 처리를 어떻게 하고 있을까? (0) | 2022.08.13 |
댓글