I would like to know what is the best practice for parent-child component interaction and whether the following approach satisfies good practices.
Let's say that we have two components: Parent
and Child
, where Parent gets handlers on Child in a fashion similar to that of obtaining a ref on element.
class Parent extends React.Component<{}, {}> {
private handlers: {
Child: ChildHandlers
/** And so on... **/
};
render() {
return (
<div>
<Child handlers={(handlers: ChildHandlers) => { this.handlers.Child = handlers; }} />
<button onClick={() => this.handlers.Child.toggle() /** Or change Parent.state and then trigger **/}>toggle from parent</button>
</div>
);
}
}
class Child extends React.Component<ChildProps, ChildState> {
constructor(props: ChildProps) {
super(props);
this.exposeHandlers();
}
private toggle(): void {
this.setState({ visible: !this.state.visible });
}
private exposeHandlers() {
let handlers: ChildHandlers = {
toggle: () => this.toggle()
};
this.props.handlers(handlers);
}
render() {
return (
<div>
{ this.state.visible && (
<div>
<h2>I'm being toggled!</h2>
<button onClick={() => this.toggle()} />toggle from child<button>
</div>
) }
</div>
);
}
}
It seems to be fine because:
toggle
method to perform some actions on Parent after updating Child's state.But since I'm not experienced, are there any (even slightest) problems with that?
Seems like an overkill to me.
What's wrong with exposing those methods and just having a reference in Parent
to an instance of Child
and then invoke those methods when needed?
Parent:
class Parent extends React.Component<{}, {}> {
private child: Child;
render() {
return (
<div>
<Child ref={ el => this.child = el } />
<button onClick={() => this.child.toggle()}>toggle from parent</button>
</div>
);
}
}
Child:
class Child extends React.Component<{}, ChildState> {
public toggle(): void {
this.setState({ visible: !this.state.visible });
}
render() {
if (!this.state.visible) {
return <div />;
}
return (
<div>
<div>
<h2>I'm being toggled!</h2>
<button onClick={() => this.toggle()}>toggle from child</button>
</div>
</div>
);
}
}