I have the following component, that contains a dropdown whose items open a modal, by calling a method on a child component:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.modal = React.createRef();
}
render() {
...
let dropdownItems;
if (isCreate) {
dropdownItems = <>
{ /* Calling open() on the child component */ }
<Dropdown.Item onClick={() => {this.modal.current.open()}}>Create</Dropdown.Item>
</>;
} else {
dropdownItems = <>
{ /* Same thing, from another item */ }
<Dropdown.Item onClick={() => {this.modal.current.open()}}>Edit</Dropdown.Item>
<Dropdown.Item>Delete</Dropdown.Item>
</>;
}
return (
<Dropdown>
<Dropdown.Toggle as={CustomDropdownToggle} id={dropdownId} />
<Dropdown.Menu>
<Dropdown.Header>...</Dropdown.Header>
{dropdownItems}
{ /* Storing a reference to the child component */ }
<EditMatchModal ref={this.modal} productMatch={productMatch} />
</Dropdown.Menu>
</Dropdown>
);
}
}
class EditMatchModal extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
}
open() {
this.setState({ isOpen: true });
this.loadData();
}
loadData() {
// Perform AJAX request...
}
render() {
return (
<Modal>
...
</Modal>
);
}
}
This works fine, however I read here and in the docs that refs are an escape hatch, that should usually be avoided.
What's a better alternative to avoid the usage of refs in this case?
One solution would be to move the isOpen
property to the parent MyComponent
, but:
- it really feels like it belongs to the modal component
- when changed, it must immediately trigger an AJAX request, so it makes sense to have the method located on the modal where the AJAX code lies
Another solution would be to move the buttons that open the modal to the EditMatchModal
itself, but:
- there are 2 buttons, so this would duplicate the modal component (is this a big deal?)
- the buttons are not just buttons, but
<Dropdown>
items, so the presentation of the parent component would leak into the child component, which is a big smell to me
Did I miss something?
` styles based on the `show` prop. But it also says "Modals are unmounted when closed." So a bootstrap modal is really also conditionally rendering everything *within* its ` ... ` tags.
– Seth Lutske Feb 13 '20 at 16:43