본문 바로가기

Solution & What I learn

[React, Redux - Project] 댓글 서비스 구현하기 | Issue & Solution

반응형

 📚 issue & problem

 

1.remove action을 실행했을 때 URL에 [object%20Object] 가 찍히는 현상

 

        case REMOVE_COMMENT:
            return {
                ...state,
                comments: state.comments.data.filter(
                    (comment) => comment.id !== action.id
                ),
            };

 

- reducer를 잘못 작성했었던 것 같다..

 

 

2. 수정누르면 클릭한 해당 데이터가 form 컴포넌트로 이동해야 한다. 

 

getComment api로 수정 버튼이 클릭된 데이터를 불러온다.

 

export const getComment = async (id) => {    
  const response = await axios.get(`http://localhost:4000/comments/${id}`);    
  return response.data;
};

 

불러온 데이터를 초기 데이터에 저장하고 form 컴포넌트에서 해당 데이터를 불러오도록 했다.

 

 

3. form value 설정 오류

 

 위와 같은 오류 발생

 

시도 1)

 

<input
    type="text"
    name="profile_url"
    placeholder="https://picsum.photos/id/1/50/50"
    required
    onChange={onChange}
    value={profile_url}
/>

 

- 위 코드에서 value를 → defaultValue로 지정

 

<input
    type="text"
    name="profile_url"
    placeholder="https://picsum.photos/id/1/50/50"
    required
    onChange={onChange}
    defaultValue={profile_url}
/>

 

 

시도 2) 


-  수정 시에는 폼이 초기화되었지만, 등록 시에는 폼이 초기화되지 않는 버그를 발견했다.

- 다시 찾아보니 value 값 지정 후 없다면, value를 빈 값으로 할당하는 것으로 수정 => 정상적으로 폼이 초기화됨

 

<input
    type="text"
    name="profile_url"
    placeholder="https://picsum.photos/id/1/50/50"
    required
    onChange={onChange}
    value={profile_url || ""}
/>

 

 

4. pagination 기능 구현

 

시도 1) 

 

currentPage = 현재 페이지 (1)

postPerPage =  보여줄 게시물 수(10)

 

const indexOfLastPage = 현재 페이지 * 보여줄 게시물 수 (= 현재 페이지에서 마지막 게시물의 index)

const indexOfFirstPost = 현재 페이지 * 보여줄 게시물 수  - 보여줄 게시물 수  (= 현재 페이지에서 첫 번째 게시물의 index)

const currentPosts =  전체게시물.slice(현재 페이지에서 첫 번째 게시물의 index,  현재 페이지에서 마지막 게시물의 index)

 

- 페이지네이션은 처음 구현해봐서 이것저것 다양한 레퍼런스를 많이 찾아봤다. (그런데 다들 비슷한 방식으로 구현하네..?)

 

시도 2)

 

- 위 코드는 포기하고 다른 방식으로 돌렸다. 

위 코드는 처음 렌더링 되는 컴포넌트 내부에 pagination 컴포넌트가 들어있다면 구현이 가능했다. 하지만 pagination 컴포넌트와 데이터를 받아오는 컴포넌트가 분리되어있을 경우 복잡해진다.. (왜냐면 currentPosts가 데이터를 받아오는 컴포넌트에서 실행되어야 하는데 변수에 할당되어있는 데이터만 옮기기는... )

 

페이지 별로 데이터를 불러오는 방식으로 다시 진행하기로 했다. 페이지별로 api를 새로 받아오기로 했다.

 

`http://localhost:4000/comments?_page=${num}&_limit=4&_order=desc&_sort=id`

 

위 api는 페이지네이션 컴포넌트에서 클릭된 number를  받아와서 해당 api로 보내주면 페이지 버튼을 누를 때마다 그에 맞는 데이터를 받아온다.

 

=> 여기서 이제 모든 데이터를 받아오는 api가 필요하지 않게 되어 정리하려고 했는데, 총데이터의 수를 계산해야 해서 모든 데이터를 불러오는 api를 dispatch 하고 해당 data의 length를 구해서 계산했다. (이렇게 코드를 짰는데, 뭔가 불필요하게 api를 또 받아온다는 생각이 든다. 총데이터의 개수를 불러오는 api는 원래 없는 건가..)

 

 

5. 수정 시 페이지 유지 / 입력, 삭제 시에는 1페이지로 돌아가기

 

//thunk - page에 따른 데이터를 받아오기
export const pageComments = (num) => async (dispatch) => {
    dispatch({ type: PAGE_COMMNETS });
    try {
        const payload = await commentsApi.pageComments(num);
        dispatch({
            type: PAGE_COMMNETS_SUCCESS,
            payload,
            currentPage: num, //받아온 페이지의 number
        });
    } catch (e) {
        dispatch({
            type: PAGE_COMMNETS_ERROR,
            error: e,
        });
    }
};


//reducer - page에 따른 데이터를 받아올 때, 성공시 작업
case PAGE_COMMNETS_SUCCESS:
    return {
        ...state,
        comments: {
            loading: false,
            data: action.payload,
            error: null,
        },
        currentPage: action.currentPage, // 받아온 page의 number
    };

 

- 페이지에 따른 데이터를 받아오는 api에 현재 페이지의 number을 가져올 수 있도록 수정하여 각 액션마다 원하는 페이지로 돌아갈 수 있도록 수정했다. redux의 initialState에 currentPage를 1페이지로 지정해두어 초기 데이터를 받아올 시 1페이지의 데이터를 받아오고, 액션 발생 시 page의 number을 함께 전달하도록 했다.

 

 

6. json-server와 함께 배포하기

 

이 프로젝트는 json-server가 포함된 프로젝트이다. 보통 내가 프로젝트 배포시 gh-pages나 netlify를 사용했는데 이 서비스들은 정적 웹사이트 배포에 최적화 되어 있는 서비스여서 이 문제를 해결하는데 꽤 오랜 시간을 두고 찾아봤다. 결국 json-server를 같이 배포할 수 있다는 heroku로 배포를 진행하게 되었다. (관련하여 아래 링크에 더 자세한 과정을 남겨뒀다. )

 

 

 

Heroku로 react 프로젝트 배포하기 (json-server 포함)

json-server가 프로덕션 전용이 아닌 것을 알지만, 백엔드 서버가 없기 때문에.. 프로젝트 배포 시 json-server도 같이 배포하기 위해 여러 배포 서비스를 찾아봤다. 그전에 가장 쉽게 접근 가능한 gh-pag

heeyeonjeong.tistory.com

 


 

 

🔨 what i learn + 개선 사항

 

1. 전체 데이터를 받아오기보다 필요한 데이터를 받아와서 페이지에 보여주기

2. 불필요한 렌더링 개선하기

3. api 요청 시마다 로딩, 성공, 실패에 따른 액션이 모두 있기보다, 해당 api의 기능에 따라 액션을 만들기 (굳이 다~ 있을 필요는 없다.)