포스트 리스트를 구현한 것 까지는 좋았지만, 사용자의 입장에서는 불편할 수 있는 점이 보인다.
예를 들면 항목하나를 클릭해서 로딩을 통해 데이터를 보여주고 난뒤, 뒤로 가면 로딩시간을 또 기다려야 한다.
굳이 이렇게 다시 로딩을 해서 기다려야 할까? 더 좋게 만들 수는 없을까?
재로딩 해결은 간단하다. PostListContainer에서 useEffect의 내용을 수정해주면 된다.
데이터가 있다면? dispatch하지 마라.
useEffect(() => {
if(data) return;
dispatch(getPosts())
},[dispatch, data])
이렇게 data 값이 있다면 그냥 return 하게 하면 된다.
이제 뒤로가기를 눌러도 로딩중이라는 문구가 나타나지 않는다.
여기서 더 개선해서 로딩중이라는 문구는 나타나지 않고 ,데이터를 업데이트하는 기능을 추가해보다.
asyncUtils.js 에서 handleAsyncActions 에서 새로운 파라미터를 추가한다.
keepData : true 일 경우 state[key].data로 업데이트를 하고, false 일 경우는 null로 변경한다.
export const handleAsyncActions = (type, key, keepData) => {
const [SUCCESS, ERROR] = [`${type}_SUCCESS`, `${type}_ERROR`];
return (state, action) => {
switch (action.type) {
case type:
return {
...state,
[key]: reducerUtils.loading(keepData ? state[key].data : null),
};
PostListContainer.js 에서 useEffect에 작성한 내용 대신에 loading && !data일 경우 로딩중 화면을 렌더링하게 수정해준다.
useEffect(() => {
dispatch(getPosts())
},[dispatch])
if (loading && !data) return <div>로딩중...</div>
if (error) return <div>에러 발생!</div>
if (!data) return null
마지막으로 유틸함수에서 keepData 파라미터를 추가했으니, posts.js 모듈에서도 파라미터를 추가해야한다.
const getPostsReducer = handleAsyncActions(GET_POSTS, 'posts', true)
이제 다시 돌려보면
뒤로가기로 메인화면으로 돌아갈때 로딩중... 이라는 화면은 나타나지 않지만, GET_POSTS와 GET_POSTS_SUCCESS가 dispatch되는 모습을 볼수 있다.
두번째 문제는 항목을 클릭하고 뒤로와서 다른 항목을 클릭하면 짧은 시간 동안 이전의 항목 데이터가 보여지는 현상이 생긴다.
gif 로는 잘 안보이지만, 육안으로 봤을때는 현상이 잘 보인다.
posts.js 모듈에서 CLEAR_POST 라는 액션 타입을 추가한다.
const CLEAR_POST = 'CLEAR_POST'
그리고 thunk 생성함수도 하나 추가한다.
export const clearPost = () => ({type: CLEAR_POST})
리듀서에도 case를 하나 추가해서 데이터값을 initial값으로 초기화 하는 동작을 추가한다.
case CLEAR_POST:
return {
...state,
post: reducerUtils.initial()
}
PostContainer.js 에서 useEffect의 내용을 수정한다. 뒤로가기를 누르면 clearPost가 dispatch 되게끔 return 값을 지정한다. 따라서 postId 값이 바뀌거나 컴포넌트가 unmount 되면 getPost를 dispatch 하기 직전에 clearPost가 먼저 dispatch된다.
useEffect(()=> {
dispatch(getPost(postId))
return () => {
dispatch(clearPost())
}
},[postId, dispatch]);
clearPost가 먼저 dispatch되어 post의 data를 null값으로 변경되어서 이전의 데이터 내용이 전혀 보이지 않게 되었다.