我正在尝试实现一个特定的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>
现在考虑我们不能/不应从父组件调用子组件方法的反应方式。在这里,我想在每个组件中保留一个isValid
方法,单击Wizard
按钮后,将从父Next/Finish
组件中调用该方法。反应方式建议将状态和逻辑移到父组件。但是那样,我将无法重用相同的组件,例如ComponentA
在任何其他向导或任何其他位置,否则我将不得不在每个使用ComponentA
的父组件中重复验证逻辑。使用ref
或this approach,我可以轻松访问子组件的方法(isValid
)。
截至今天(反应版本16.6),我还没有看到需要根据需要使用此模式进行反应的任何陷阱。在反应中使用此模式可能会遇到什么问题?在此特定示例中,还有没有更好的选择可用来使isValid
方法保留在步骤组件中(例如ComponentA
)以供重用?
答案 0 :(得分:2)
是的
在典型的React数据流中,道具是父组件与其子组件交互的唯一方式。要修改孩子,您可以使用新道具重新渲染它。
您的第一个倾向可能是使用引用在应用中“使事情成真”。如果是这种情况,请花点时间仔细考虑一下状态在组件层次结构中应拥有的位置。
创建引用是为了在特定用例(焦点,文本选择,媒体播放,第三方库等)中访问DOM,但在尝试使其他组件执行操作时应避免使用它们。
因此,您当然可以拥有一个React应用程序,该应用程序在使用ref调用子组件方法时可以运行,但是是的,这是非常反模式的。
答案 1 :(得分:1)
简短的回答:在您的情况下,这种方法还可以。只要情况发生变化,只需重新访问即可。
说明:
这不是您情况中的反模式。如果您通过ref控制子组件的行为,它将被视为反模式。
反应时建议避免使用此类反模式,而一般建议避免在某些极端情况下使组件受到不同的事实来源控制而变得不稳定。但是,在像您这样的场景中,您可以确定为什么要使用它,这很好。
例如,React建议不要从道具填充状态。之所以如此,是因为您有两个事实来源,需要同步它们,否则您的组件将无法正常工作。但是,如果您确定自己的道具(特别是数据)不会改变,那么它就不再是反模式了,因为您现在从道具中播种状态,但随后仅在状态级别进行管理。>