라는 생각으로 useFetch를 만들어 보았다
usePost
import { useState } from "react";
const usePost = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const postRequest = async (url, body = {}) => {
setLoading(true);
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error("네트워크 상태가 올바르지 않습니다.");
}
const result = await response.json();
setData(result);
setError(null);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
return { data, loading, error, postRequest };
};
export default usePost;
post에 대한 useFetch 커스텀 훅이고
로그인 테스트에 사용해보았다
아래는 로그인 이벤트 함수이다
submitData
const submitData = async () => {
if (!idValueValidation(idValue)) {
return;
}
if (!pwValueValidation(pwValue)) {
return;
}
await postRequest(`${process.env.REACT_APP_API_KEY}/account/auth`, {
id: idValue,
pw: pwValue,
});
if (loading) {
return <Div>로그인 중 입니다.</Div>;
}
if (error) {
return <Div>Error{error.message}</Div>;
}
if (data && data.token) {
setCookies("token", data.token, { path: "/" });
navigate("/");
}
};
비동기로 진행하고 통신을 마치면 그 결과를 state에 적용시켜 그 state에 따라 if문이 동작하는 구조로 만들었다
그리고 실행하니
분명 계속 로그인이 안 되는 것이 아니라 두 번을 눌러야 된다는 것은 state의 값이 제대로 반영이 되지 않았다는 뜻 같았다
react state에 대해 찾아보니
두가지 질문
먼저 react Batching에 대해 알아야 한다
리액트에 최적화를 위해 사용되는데 예를 들어
function App() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount((count) => count + 1);
setCount((count) => count + 1);
setCount((count) => count + 1);
};
useEffect(() => {
console.log("count", count);
}, [count]);
return <button onClick={handleClick}>+</button>;
}
이 state를 콘솔로 찍어본다면
Count 1,2,3이 아닌
count 3이 나온다
리액트는 단기간에 발생하는 state에 변화에 대해
하나하나 리렌더링을 동작시키는게 아니라
일괄로 처리함으로 써 성능을 최적화 한다
간단하다 useEffect를 사용하여 state의 변화에 따라
조건을 주면 된다
즉 한 함수 안에서 if문을 돌리는 것이 아니라
해당 조건문을 따로 때어서 로그인 이벤트 함수가 실행되고 난 뒤
state의 변화에 따라
조건문을 실행하는 것이다
useEffect(() => {
if (loading) {
console.log("로그인 중 입니다.");
} else if (error) {
console.error("Error:", error.message);
} else if (data && data.token) {
setCookies("token", data.token, { path: "/" });
navigate("/");
}
}, [loading, error, data, setCookies, navigate]);
const submitData = async () => {
if (!idValueValidation(idValue)) {
return;
}
if (!pwValueValidation(pwValue)) {
return;
}
await postRequest(`${process.env.REACT_APP_API_KEY}/account/auth`, {
id: idValue,
pw: pwValue,
});
};
이렇게 바꾼다면 로그인 버튼을 두 번 누르지 않아도
결과값에 따라 state가 변화될 것이고 그것을 useEffect로 다시 렌더링 한다