리액트 현재 Tabmenu 클릭으로 리렌더링 하는 법

now·2024년 10월 14일

react

목록 보기
1/3
post-thumbnail

커스텀 탭 컴포넌트를 사용하는 중에 해당 탭을 클릭하면 탭이 다시 렌더링 되도록 하는 기능이 필요했는데 react 특성상 탭을 클릭한다고 해서 해당 탭을 리렌더링 하지 않았다.

  • 문제점: tabpanel component에서 current tab을 눌러도 rerendering 이 일어나지 않음.
    • 이유: React's reconciliation process
      리엑트는 DOM을 현재 previous tree와 현재 tree를 비교하여 변화에 따라 효율적으로 업데이트 시키는데 props 혹은 state가 전혀 변화하지 않았기 때문에 리렌더링 되지 않는다.
  • 해결방법: current tab을 클릭 할 때 해당 panel의 props인 key를 변경해주면 리렌더링 됨
function CustomTabWithPanel(props: Props): JSX.Element {
    const {
        tabList,
        footer,
        tabComponent,
        isButtonType = false,
        className,
        selectedTab,
        childrenProps = {},
        reset,
        ...rest
    } = props;
    const [updateTrigger, setUpdateTrigger] = useState<boolean>(false);

    const handleTabChange = useCallback((nextTab: number) => {
    // 추가된 부분 ==============>
        if (nextTab === state.currentTab) {
            setUpdateTrigger(!updateTrigger);
        }
    //=========================/
        dispatch(actions.changeTab(nextTab));
        if (typeof reset === 'function') reset();
    }, []);

    return (
        <Box className={className} {...rest}>
            <TabContext.Provider value={{ state, dispatch }}>
                <Box>
                    <BoTabs
                        tabComponent={tabComponent}
                        currentTab={state.currentTab}
                        tabList={tabList}
                        onChange={handleTabChange}
                        isButtonType={isButtonType}
                    />
                </Box>
                {tabList.map((tab) => (
                    <CustomTabPanel 
                    	// key 변경 ===============> 
                        key={`${tab.key}-${updateTrigger}`}
                        // =======================/
                        currentTab={state.currentTab} 
                        index={Number(tab.key)}
                    >
                        <Box sx={{ pt: 1 }}>{React.cloneElement(tab.component as any, { ...childrenProps })}</Box>
                    </BoTabPanel>
                ))}
            </TabContext.Provider>
            {footer}
        </Box>
    );
}

0개의 댓글