history.push()/replace() 렌더링 문제
요즘 리액트와 몽고DB를 연동시켜 간단한 텍스트 CRUD 게시판을 구현하고 있는 도중 맞닥뜨린 문제다. 글 작성을 완료하고 목록으로 돌아가기 위해서 useHistory() push('/path~')로 연결해 줬다. 목록으로 돌아갔을 때는 다시 리렌더링 돼서 작성한 글까지 목록에 보여야 하는데... 작성한 글이 업데이트가 안 되는 것이 문제다.
기존 글 목록을 불러오는 방법은 아래와 같다.
//main 컴포넌트
useEffect(()=>{
axios.get('/post/list')
.then((res) => {
setPost(res.data); //글 목록 업데이트
setNowload(false); //로딩종료 및 목록 렌더링
}).catch((err) => {
console.log(err);
setNowload(true); //목록 숨기기 및 로딩 시작
});
}, []);
useEffect로 최초 렌더링 되기 전 한 번만 목록을 불러오도록 했다.
//write 컴포넌트
const onSubmit = ((e)=>{
e.preventDefault();
if(title !== '' && body !== ''){
const title = titleInput.current.value;
const body = bodyInput.current.value;
axios({
method : 'post',
url : '/post/write/new',
data : {
title : title,
body : body
}
}).then((res)=>{
if(res.status === 200){
his.push('/list');
}
}).catch(err=>{
console.log(err);
});
}
})
write 컴포넌트에서 글 작성이 완료되면 '/list 경로로 이동해서 방금 작성한 글 목록까지 불러와서 렌더링 해주어야한다. push를 할 때는 경로뿐만 아니라 스테이트도 넘겨줄 수 있어서 활용해보려 했지만 무한 렌더링 뜨고 정확히 딱 한 번만 렌더링 해주기 위해서 그냥 리스트 업데이트 함수를 추가해줬다.
해결방법
// Main 컴포넌트
const listUpdate = () =>{
setNowload(true);//로딩 시작
axios.get('/post/list')
.then((res) => {
setPost(res.data); //목록 업데이트
setNowload(false); //로딩 종료 및 목록 렌더링
}).catch((err) => {
console.log(err);
setNowload(true); //목룩 숨기기 및 로딩 시작
});
}
//write 컴포넌트
const onSubmit = ((e)=>{
e.preventDefault();
if(title !== '' && body !== ''){
const title = titleInput.current.value;
const body = bodyInput.current.value;
axios({
method : 'post',
url : '/post/write/new',
data : {
title : title,
body : body
}
}).then((res)=>{
if(res.status === 200){
listUpdate(); //<-- 목록 업데이트 함수 실행
his.push('/list');
}
}).catch(err=>{
console.log(err);
});
}
})
write 컴포넌트에 글 목록 업데이트 함수를 넘겨 줬고 아래 서브밋 함수가 실행되고 글 작성이 완료되면 Main 컴포넌트의 글 목록 업데이트 함수가 정확히 딱 1번 실행돼서 목록에는 새로 작성한 게시글까지 정상적으로 업데이트가 됐다.
First Rendering은 useEffect로 렌더링 했을때, Second Rendering은 글 작성 완료했을때!