Hiding state, simplifying modal dialogs usages
Similarly to lifting state up, in some scenarios you might not care how a piece of state is managed. Like for example, a modal dialog with an isOpen
property that decides if the dialog is open or not. react-modal works like this:
<Modal isOpen={true}>
<div>... modal dialog content here</div>
</Modal>
This offers a great deal of flexibility, but a problem arises, whenever you need to use this modal component you’ll also need to add logic to control whether the dialog is open or not. One solution could be creating a base class for all modal dialogs and manage the isOpen
state there, but inheritance is usually not recommended in React. There’s a better way.
It should be possible to extract the logic that controls the isOpen
property from the content of the dialog and the component that takes care of launching it. This seems like a good use case for render props. The following ModalManager
is a possible solution, it has a property component
that returns a button or whatever element is responsible for displaying the modal. And the children
property, also a render prop, will return the content of the modal.
<ModalManager
component={showModal => <button onClick={showModal}>Show Modal</button>}
>
{({ hideModal }) => (
<div>
<h1>Modal content</h1>
<button onClick={hideModal}>Hide modal</button>
</div>
)}
</ModalManager>
This will make using a modal dialog easier since it’s completely abstracted from all the logic concerned with the state of the modal dialog. Assuming we have a separate Modal
component (like the one provided by react-modal), implementing ModalManager
is simple.
class ModalManager extends React.Component {
state = {
modalOpen: false
};
showModal = () => this.setState({ modalOpen: true });
hideModal = () => this.setState({ modalOpen: false });
render() {
return (
<React.Fragment>
{this.props.component(this.showModal)}
<Modal isOpen={this.state.modalOpen} onRequestClose={this.hideModal}>
{this.props.children({
hideModal: this.hideModal
})}
</Modal>
</React.Fragment>
);
}
}
Here’s the basic example from react-modal modified to use ModalManager
.
See the Pen Sample: ModalManager, hiding state with render props by Ariel Rodriguez Romero (@arielsvn) on CodePen.
This class is used several times in refinebio, there ModalManager
has other properties to support more use cases. I should also thank ramenhog since we came up with this together.
Render props are a very powerful technique in React, I can’t stop using it now that I learned about it. The first person I heard mention it was Michael Jackson, one of the creators of react-router.
I can do anything you're doing with your HOC using a regular component with a render prop. Come fight me.
— MICHAEL JACKSON (@mjackson) July 14, 2017