在react中从 Parent 调用子组件的方法是反模式吗?为什么?

IT技术 javascript reactjs reactive-programming
2021-05-05 16:33:31

我正在尝试实现Wizard用户可以使用以下模式使用的特定组件。

<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>

现在考虑我们不能/不应该从父组件调用子组件的方法的react方式。在这里,我想isValid在每个组件中保留一个方法,方法将Wizard在单击Next/Finish按钮时从父组件调用React 方式建议将状态和逻辑移动到父组件。但是那样我将无法重用相同的组件,例如ComponentA在任何其他向导或任何其他地方,或者我将不得不在每个使用ComponentA. 使用ref这种方法我可以轻松访问子组件的方法(isValid)。

截至今天(React 版本 16.6),我没有看到在react中根据需要使用此模式的任何陷阱。在 React 中使用这种模式可能会遇到什么问题?在这个特定示例中是否有更好的选择,我可以使用它isValid在步骤组件(例如ComponentA)中保留方法以供重用?

2个回答

简答

是的。

长答案

来自React 的 refs 文档

在典型的 React 数据流中,props 是父组件与其子组件交互的唯一方式。要修改一个孩子,你需要用新的props重新渲染它。

您的第一个倾向可能是在您的应用中使用 refs 来“使事情发生”。如果是这种情况,请花点时间更批判性地思考状态应该在组件层次结构中的哪个位置拥有。

创建 Refs 是为了在特定用例(焦点、文本选择、媒体播放、第三方库等)中访问 DOM,但在尝试让其他组件执行操作时应避免使用它们。

所以当然你可以有一个 React 应用程序,它可以在使用 refs 调用子组件方法时工作,但是是的,它是非常反模式的。

简短回答:您的场景中的这种方法没问题。只需在您的场景发生变化时重新访问它。

说明

在您的场景中,这不是反模式。如果您通过 ref 控制子组件的行为,它将被视为反模式。

React 建议避免像一般建议那样的反模式,以避免在极端情况下,您的组件由于受到不同来源的控制而变得不稳定。但是,在您确定使用它的原因的情况下,这很好。

例如,React 建议不要从 props 填充 state。这是真的,因为你有两个事实来源,你需要同步它们,否则你的组件将无法正常运行。但是,如果您确定,您的props(特别是数据)将不会改变,它不再是一种反模式,因为您现在正在从props中播种状态,但它会继续仅在状态级别进行管理。