简体   繁体   中英

Reuse React component from render props

I wrote a react component in render props way,it will call children function with 3 react component object ( not sure the name exactly, the variable generated by executing jsx (<div>...</div>) );

<PaginatedTable> Usage example:

<PaginationTable data={data} ...otherprops>
    {({ SearchBar, Table, PaginationBar })=>
        (<div>
            {SearchBar}
            {Table}
            {PaginationBar}
        </div>)
    }
</PaginationTable>

with render props, I'm so glad that I can custom these 3 child component object very easily such as rearrange order or adding custom elements between these three.

{({ SearchBar, Table, PaginationBar })=>
        (<div>
            {PaginationBar}
            <h1> my custom search bar text </h1>
            {SearchBar}
            {Table}

        </div>)
    }

But now I wish more than arrange order inside , I wish I can move {SearchBar} out of to the same layer of 's sibling 's children such as this picture.

working demo: https://codesandbox.io/s/23q6vlywy

在此处输入图片说明

I thought this may be anti-pattern to the unidirectional data flow of React.

Extract {SearchBar} to another independent component then use it as <SearchBar ... /> inside of <ToolBarArea /> is what I learnd from React Doc.

But in this way, I have to do "lifting state up" and write similar function and states already had in <PaginationTable /> like below **text** parts are functions and states already had in <PaginationTable />

class ToolBarArea extends Component{
    render(){
        return(
        <div>
            // text
            <SearchBar onChange={**this.props.onSearchBarChange**} />
            //.... other text or elements
        </div>);
    }
}
class ContainerArea extends Component {
    state={
        **searchBarText:'',**
        tableData : [{...}, {...}]
    }
    **onSearchBarTextChange = (event)=>{
        this.setState({ searchBarText: event.target.value });
    }
    filterdTableData = ()=> this.state.tableData.filter(d=>d.name.includes(this.state.searchBarText);
    **
}

I really hope there is a way I can simply move the variable {SearchBar} in the render props function out to without knowing is in the parent or parent's sibling or anywhere in the DOM tree.

such as

<ToolBarArea>
    {SearchBar} // SearchBar from <PaginationTable />
</ToolBarArea>

Is there a way to reuse onSearchBarTextChange and filtedTableData functions and these **text** codes I already wrote in <PaginationTable /> ?

I believe you hit the nail on the head when you referred to lifting state. If you already wrote a similar function then your best option may be to 'abstract' that function so that it applies to both use cases. You could use a simple flag to differentiate the unique execution each needs. Then finally pass the function down to both components.

If you're adamant about avoiding this approach you could technically get around it by using event listeners to handle data transfer or watch variables in the window but this is for sure an anti-pattern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM