React 자식을 분해하여 DX 향상

17803 단어 tabsdxchildrenreact
오늘은 탭 시스템을 만들어야 했습니다.
작은 공간에 여러 유형의 데이터를 표시하는 데 완벽한 탭 시스템은 두 부분으로 구성됩니다.
  • 헤더에 항상 모든 탭 레이블이 표시됨
  • 콘텐츠 부분에 선택한 탭과 관련된 데이터가 표시됩니다
  • .

    이러한 종류의 시스템의 복잡성은 고정 부분과 동적 부분이 있다는 것입니다. 두 가지 구현을 살펴보겠습니다.

    V1 – 코딩은 간단하고 사용하기 어려움



    첫 번째 아이디어는 다음과 같이 호출할 수 있는 tabslabel가 있는 객체 배열에 해당하는 content 소품으로 간단한 구성 요소를 수행하는 것입니다.

    <TabView
        tabs={[
            {
                label : "First tab", 
                content : <p>My first tab content</p>
            },
            {
                label : "Second tab",
                content : <p>My second tab content</p>
            },
            {
                label : "Third tab",
                content : <p>My third tab content</p>
            }
        ]}
    />
    


    내용을 변수에 넣을 수 있지만 예제용입니다.
    해당<TabView> 구성 요소는 다음과 같아야 합니다.

    const TabView = ({tabs}) => {
        const [selectedTabIndex, setSelectedTabIndex] = useState(0)
    
        return (
            <div>
                <div className="header">
                    {tabs.map(tab => (
                        <p>{tab.label}</p>
                    ))}
                </div>
                <div className="content">
                    {tabs[selectedTabIndex].content}
                </div>
            </div>
        )
    }
    


    첫 번째 문제는 조건부 탭이 필요하고 이 구성으로는 복잡합니다 😕
    탭을 변수에 넣고 필요한 경우 선택적 탭을 추가해야 합니다... 다음과 같습니다.

    const displayThirdTab = ...
    
    const tabs = [
        {label : "First tab", content : <p>My first tab content</p>},
        {label : "Second tab", content : <p>My second tab content</p>}
    ]
    
    if(displayThirdTab){
        tabs.push({label : "Third tab", content : <p>My third tab content</p>})
    }
    
    return (
        <TabView
            tabs={tabs}
        />
    )
    


    사용하기가 복잡해지기 시작했고 더 잘할 수 있습니다. 내 <TabView> 구성 요소를 변경하면 다음과 같이 사용되는 보다 개발 친화적인 구성 요소를 만들 수 있습니다.

    <TabView>
        <Tab label="First tab">
            <p>My first tab content</p>
        </Tab>
        <Tab label="Second tab">
            <p>My second tab content</p>
        </Tab>
        {
            displayThirdTab && (
                <Tab label="Third tab">
                    <p>My third tab content</p>
                </Tab>
            )
        }
    </TabView>
    


    V2 – 코딩하기 어렵지 않고 훨씬 사용하기 쉽습니다.



    위 구성 요소의 어려움은 고정 부분에 있습니다. 자식의 일부만 표시해야 합니다.

    이를 위해 아무것도 렌더링하지 않는 <Tab>라는 "고스트 구성 요소"를 생성하는 것으로 시작합니다.

    const Tab = ({tabs}) => {
        //Rendered in TabView component
        return null
    }
    


    typescript를 사용하여 사용하는 데 필요한 소품을 지정할 수 있습니다<TabView>.

    그럼 <TabView> 컴포넌트의 베이스를 작성해보겠습니다.

    const TabView = ({children}) => {
        const [selectedTabIndex, setSelectedTabIndex] = useState(0)
    
        const tabsInfo = []
        const tabsContent = []
    
        //TODO : Parse children
    
        return (
            <div>
                <div className="header">
                    {tabsInfo.map(({label}) => (
                        <p>{label}</p>
                    ))}
                </div>
                <div className="content">
                    {tabsContent[selectedTabIndex]}
                </div>
            </div>
        )
    }
    


    두 개의 배열을 볼 수 있습니다.
  • tabsInfo에는 모든 탭 헤더 데이터가 포함됩니다(이 경우 레이블만 해당)
  • .
  • tabsContent에는 모든 <Tab> 구성 요소children 소품
  • 이 포함됩니다.

    이제 배열을 채우기 위해 children prop을 파싱해야 합니다.
    이를 위해 parseTab라는 함수를 추가합니다.

    const parseTab = (node) => {
        //We extract children from the <Tab> props
        tabsContents.push(node.props.children)
        //We extract label from <Tab> props 
        tabsInfo.push({ label: node.props.label })
    }
    


    React.Children.map 이 있는 자식의 각 노드에 대해 호출하기만 하면 됩니다.

    React.Children.map(children, parseTab)
    


    최종<TabView> 구성 요소입니다.

    const TabView = ({children}) => {
        const [selectedTabIndex, setSelectedTabIndex] = useState(0)
    
        const tabsInfo = []
        const tabsContent = []
    
        const parseTab = (node) => {
            //We extract children from the <Tab> props
            tabsContents.push(node.props.children)
            //We extract label from <Tab> props 
            tabsInfo.push({ label: node.props.label })
        }
    
        React.Children.map(children, parseTab)
    
        return (
            <div>
                <div className="header">
                    {tabsInfo.map(({label}) => (
                        <p>{label}</p>
                    ))}
                </div>
                <div className="content">
                    {tabsContent[selectedTabIndex]}
                </div>
            </div>
        )
    }  
    

    좋은 웹페이지 즐겨찾기