TIL(0419)

L·2022년 4월 19일
0

TIL

목록 보기
1/5

😨특정 컴포넌트 클릭시 무한랜더링 현상

이번에 지원한 회사에 서류전형에 합격되어 1주일동안 과제를 했다. react프레임워크를 이용한 간단한 프로젝트 구현이었는데, 리엑트는 jsx이후로는 한적이 없어서 쉬운 주제였음에도 초반에 고전을 면치못했다. useState,useEffect이거 두개만 있으면 구현하는데 큰문제가 없는 과제였다.(rendering최적화에 있어서는 이 2가지만으론 어려운것은 사실😅)

😱문제점

부모컴포넌트에서 이벤트 발생시 properties값을 넘긴 후 List컴포넌트가 무한으로 rendering되어 브라우져의 속도가 급격하게 떨어졌다.🤯

function List({param1,param2}){
    const [list,setList]=useState([]);
    const [pager,setPager]=useState({});
    const [searchParam,setSearchParam]=useState({});
    
    
    const searchList = async (param1,param2,page=0,rowsPerPage=10)=>{
      	console.log('start searchList');
         const {items,total_count} = await fetchList(param1,param2,page+1,rowsPerPage);
            setList(items.map((item)=>{return {
                    ...item,
                    login:item.user.login
                };
            }));
            setPager({
                count:total_count,
                page,
                rowsPerPage
            });
    };
	setSearchParam({param1,param2});
 	searchList(param1,param2,pager.page,pager.rowsPerPage);

    const onClickPage = async (page,rowsPerPage)=>{
        const {param1,param2} = searchParam;
        searchList(param1,param2,page,rowsPerPage)
    }

    const header = [
    {
        title:'번호',
        paramName:'number'
    },{
        title:'제목',
        paramName:'title'
    },{
        title:'작성자',
        paramName:'login'
    },{
        title:'작성일자',
        paramName:'updated_at'
    }];
    return (
        <Table
            header={header}
            list={list}
            pager={pager}
            pageClick={onClickPage}
        />
    )
}

export default List;

해당 컴포넌트는 부모 컴포넌트에서 param1param2 프로퍼티 값을 받아와서, 외부 API의 결과를 list와 pager state에 넣어 Table 컴포넌트에 전달한다.하지만 부모 컴포넌트가 render되면 해당컴포넌트가 미친듯이 랜더링이 되면서 아래 이미지 처럼 오류가 나고있었다.

🧐원인

searchList 함수의 setListsetPager을 통해 state가 변경이 되고 다시 랜더링이 되면서 state가 변경이 되고 랜더링이 되는 행위가 무한으로 반복되면서 발생.

🤗해결

searchList는 component가 mount가 됐을때만 실행을 하면 되기때문에, useEffect를 통해 해결가능.

useEffect(()=>{
//컴포넌트가 mount가 	되었을때 실행하는 함수.

});

useEffect안에 컴포넌트가 mount될때 API호출 + 상태값을 업데이트 하는 내용을 담는다.

const [pager,setPager]=useState({});
//...중략
useEffect(()=>{
//컴포넌트가 mount 되었을때 실행하는 함수.
 searchList(param1,param2,pager.page,pager.rowsPerPage);
});

하지만 이렇게 해결했음에도 아래와 같이 searchList안에 심어둔 로그가 무한대로 호출이 되고있음을 알수있다.

이를 해결하기 위해 useEffect에 두번째 parameter인 의존값이 들어가는 값들의 배열을 넣었다. 아래처럼 배열에 값이 들어가면 mount될때와 의존 값이 변경이 되면 실행이 된다. (부모컴포넌트의 값이 변경이 되거나 mount될때 안에 내용이 실행이 된다는 뜻) 만약 배열을 비우게 되면 component가 나타날때만 useEffect안에 넣은 내용이 실행된다.

function List({param1,param2}){
 const [pager,setPager]=useState({});
//...중략
useEffect(()=>{
  //컴포넌트가 mount 되었을때 실행하는 함수.
  searchList(param1,param2,pager.page,pager.rowsPerPage);
},[param1,param2]);
 //...중략
}

출처

16. useEffect를 사용하여 마운트/언마운트/업데이트시 할 작업 설정하기
Using the Effect Hook
(리엑트JS공식홈페이지)

0개의 댓글