Is it anti-pattern to call child component's method from Parent in react and why?

Viewed 1126

I am trying to implement a specific Wizard component which user can consume using the pattern below.

<Wizard {...wizardProps} onFinish={this.handleFinish}>
    <WizardStep onValidate={() => this.componentARef.isValid()}>
        <ComponentA onRef = { ref => (this.componentARef = ref)}/>
    </WizardStep>

    <WizardStep onValidate={() => this.componentBRef.isValid()}>
        <ComponentB onRef = { ref => (this.componentBRef = ref)}/>
    </WizardStep>

    <WizardStep onValidate={() => this.componentCRef.isValid()}>
        <ComponentC onRef = { ref => (this.componentCRef = ref)}/>
    </WizardStep>
</Wizard>

Now considering the react way we can't/shouldn't call child component's method from parent component. Here I want to keep a isValid method in each component which will be called from Parent Wizard component on click of Next/Finish button. React way suggest to move the state and logic to parent component. But that way I won't be able to reuse the same component e.g. ComponentA in any other wizard or any other place or I will have to duplicate the validation logic in every parent component who is using ComponentA. Using ref or this approach I can easily access the child component's method(isValid).

As of today(React version 16.6) I don't see any pitfalls using this pattern on need basis in react. What are the possible problem I may face using this pattern in react? And is there any better option in this particular example using which I can keep isValid method in step component(e.g. ComponentA) for reuse?

2 Answers

Short answer

Yes.

Long answer

From React's doc on refs:

In the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props.

Your first inclination may be to use refs to “make things happen” in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy.

Refs were created to access the DOM in specific use cases (focus, text selection, media playback, third party libs, etc), but they shall be avoided when trying to make other components execute actions.

So of course you can have a React app that works while using refs to call child component method, but yes, it is very anti-pattern.

Short Answer: This approach in your scenario is alright. Just re-visit it when your scenario get change.

Explanation:

It's not an anti-pattern in your scenario. It will be consider an anti-pattern, if you are controlling behavior of child component through ref.

React suggest to avoid such anti-patterns as general advise to avoid edge cases where your component become unstable as it get controlled by different source of truth. But, in the scenario like yours where you are sure about why you are using it, it's fine.

For example, React advise not to populate state from props. This is true because then you have two source of truth and you need to sync them otherwise your component will not behave properly. But, If you are sure that, your props (specifically data) will not be going to change, it's no longer an anti-pattern because, you are now seeding state from props but then it continue to manage at state level only.

Related