CleverPatrick
CleverPatrick

Reputation: 9483

ReactJs Create Reusable component with multiple different children

I am new to React and am trying to get up to speed on a few basic concepts, trying to shoehorn it into an existing application (with the intention of slowly converting the entire app into React). So this may be a vary basic question.

I am converting my dialogs first (my app has a bunch of bootstrap modal dialogs), so I am using react-modal library to create these dialogs. What I would like to do is make the outer markup for this dialog reusable across all my dialogs. For instance, with this render method:

render() {
        return(
            <Modal
                className="Modal__Bootstrap modal-dialog"
                closeTimeoutMS={150}
                isOpen={this.state.modalIsOpen}
                onRequestClose={this.handleModalCloseRequest}
            >
                <div className="modal-content">
                    <div className="modal-header">
                        <button type="button" className="close" onClick={this.handleModalCloseRequest}>
                            <span aria-hidden="true">&times;</span>
                            <span className="sr-only">Close</span>
                        </button>
*******INSERT HEADER COMPONENT*******
                    </div>
                    <div className="modal-body">
*******INSERT BODY COMPONENT*******    
                    </div>
                    <div className="modal-footer">
                        <button type="button" className="btn btn-default" onClick={this.handleModalCloseRequest}>Cancel</button>

*******INSERT ADDITIONAL FOOTER BUTTONS COMPONENT*******

                    </div>
                </div>
            </Modal>
        );
    }

I would like to have the lines that start with the ******** to be variable components that are appropriate (and different) for each dialog.

Obviously, for each dialog, I could just copy and paste this render method into that dialog's class and have hard coded components for that dialog. Something like (for the body):

                    <div className="modal-body">
                        <DialogABody />
                    </div>

and:

                    <div className="modal-body">
                        <DialogBBody />
                    </div>

But if I do that, I am then duplicating all the markup for the dialog "chrome" in react.

Essentially, I need some sort of dynamic component?

Is this possible?

Upvotes: 0

Views: 1578

Answers (3)

John Ruddell
John Ruddell

Reputation: 25842

on your modal react class you want to do this

class Modal extends React.Component {
    render() {
        return (
            <div>
            {this.props.header ? <HeaderComponent text={this.props.header} /> : null }
            {this.props.children}
            {this.props.footer ? <FooterComponent text={this.props.footer} /> : null }
            </div>
    }
}

then when calling this pass your props

<Modal
    className="Modal__Bootstrap modal-dialog"
    closeTimeoutMS={150}
    isOpen={this.state.modalIsOpen}
    onRequestClose={this.handleModalCloseRequest}
    header="My Header"
    footer="My Footer"
>

as for the body component part you should pass that as a prop to this dialog class when calling it.

instead of this:

<div className="modal-body">
    <DialogABody />
</div>

you should have this:

<div className="modal-body">
    {this.props.dialogComponent}
</div>

which gets passed through on the parent to this class

Upvotes: 1

gapvision
gapvision

Reputation: 1029

for one child component you could simply use this.props.children, however, as you have 3 components, you need to put them into separate props:

<DialogBody header={<div>header</div>} body={<div>body</div>} footer={<div>footer</div>}/>

Upvotes: 1

J. Mark Stevens
J. Mark Stevens

Reputation: 4945

Call your model dialog with the wanted components as props.

<model header={headerComponent} body={bodyComponent}/>

In model render just put {this.props.header} and so on.

Upvotes: 1

Related Questions