TIL(0419)


😨特定の構成部品をクリックしたときの無限レンダリング


今度応募した会社は書類審査に合格して、一週間宿題をしました.これはreactフレームワークを用いた簡単なプロジェクト実装であり、reactはjsxの後に二度とやったことがなく、簡単なテーマであるが、最初はトラブルに遭遇するのは避けられない.useState,useEffectの2つはいずれも実施に大きな問題がない課題である.(レンダリングの最適化では、この2つだけでは実現しにくい.😅)

😱に質問


親コンポーネントでは、イベントが発生したときにproperties値を超え、リストコンポーネントを無限にレンダリングし、ブラウザの速度が急激に低下します.🤯
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;
この要素は、親要素からparam1およびparam2のパーセンテージ値を取得し、外部APIの結果をlistおよびpager stateに入れてTable要素に渡す.ただし、親コンポーネントをレンダリングすると、コンポーネントが狂ったようにレンダリングされると、次の画像に示すエラーが発生します.

🧐の原因となる

searchList関数のsetListおよびsetPagerにより、状態の変更および再ロードに伴い、状態の変更およびロードされる動作が無限に繰り返される.

🤗解決する

searchListは、コンポーネントがmountになったときのみ動作するので、useEffectで解決できる.
useEffect(()=>{
//컴포넌트가 mount가 	되었을때 실행하는 함수.

});
userEffectにコンポーネントをマウントするときにAPI呼び出し+ステータス値を更新する内容が含まれます.
const [pager,setPager]=useState({});
//...중략
useEffect(()=>{
//컴포넌트가 mount 되었을때 실행하는 함수.
 searchList(param1,param2,pager.page,pager.rowsPerPage);
});
しかし、このようにして解決しても、以下に示すように、searchListに埋め込まれたログが無限に呼び出されていることがわかる.

この問題を解決するために,useEffectに第2のパラメータ依存値の配列を加えた.次の図に示すように、配列に値が含まれている場合は、マウント時と依存値の変更時に実行されます.(親コンポーネントの値が変更またはマウントされた場合、コンテンツが実行されることを示す)配列が空になっている場合、useEffectに含まれるコンテンツはcomponentが表示されている場合にのみ実行されます.
function List({param1,param2}){
 const [pager,setPager]=useState({});
//...중략
useEffect(()=>{
  //컴포넌트가 mount 되었을때 실행하는 함수.
  searchList(param1,param2,pager.page,pager.rowsPerPage);
},[param1,param2]);
 //...중략
}

ソース


16.userEffectを使用してマウント/アンインストール/更新時の操作を設定する
Using the Effect Hook (REEX JS公式ホームページ)