从多个复杂子组件中获取值的最佳方法?

我有一个父组件,它具有称为脚本的基本数据,它有多个序列,每个序列由多个项目(输入、下拉列表、...)组成。

现在我需要在父级中更新数据,因为我想放置一个保存按钮,该按钮将一键保存所有表单。

它看起来像这样:

http://img3.mukewang.com/61dfd22d0001ad5515360751.jpg

我尝试了两种处理方式:

  • 每个孩子都有一个 onChange 属性,在该属性中,父母使用新数据设置状态。但这里的问题是,由于这是一个相当复杂的表单,它每次都会重新渲染所有内容,因此在输入输入时会有明显的延迟。

  • 仅仅改变一个孩子的道具对象的“坏”,这很快,但我知道这是一种不好的做法。

在这样的规模上处理表格的最佳方法是什么?是否应该以不同的方式设置?


HUX布斯
浏览 233回答 3
3回答

慕无忌1623718

这是我花了一些时间与自己斗争的问题。有多种方法可以将子状态保持在更高级别;但是,我发现在您的特定情况下,通常最好使用 Redux。需要明确的是,我通常不惜一切代价避免 Redux(支持 React 的上下文),但 Redux 让您能够订阅子组件中的特定状态。当您只需要更新一个子组件时,侦听子组件中的一个状态将阻止您的父组件和兄弟组件更新。这在一次处理多个表单时效率更高。例如,以下组件将仅侦听影响其自身状态的状态更新。这些更新将绕过表单父组件和兄弟组件:import React from 'react';import { connect } from 'react-redux';import * as actions from 'redux/actions';// Custom componentimport { InputField } from 'shared';const FormOne = ({ me, actions }) => (&nbsp; <form>&nbsp; &nbsp; <InputField&nbsp; &nbsp; &nbsp; inputId="f1f1"&nbsp; &nbsp; &nbsp; label="field one"&nbsp; &nbsp; &nbsp; value={me.fieldOne}&nbsp; &nbsp; &nbsp; onChange={(e) => actions.setFormOneFieldOne(e.target.value)}&nbsp; &nbsp; />&nbsp; &nbsp; <InputField&nbsp; &nbsp; &nbsp; inputId="f1f2"&nbsp; &nbsp; &nbsp; label="field two"&nbsp; &nbsp; &nbsp; value={me.fieldTwo}&nbsp; &nbsp; &nbsp; onChange={(e) => actions.setFormOneFieldTwo(e.target.value)}&nbsp; &nbsp; />&nbsp; &nbsp; <InputField&nbsp; &nbsp; &nbsp; inputId="f1f3"&nbsp; &nbsp; &nbsp; label="field three"&nbsp; &nbsp; &nbsp; value={me.fieldThree}&nbsp; &nbsp; &nbsp; onChange={(e) => actions.setFormOneFieldThree(e.target.value)}&nbsp; &nbsp; />&nbsp; </form>);export default connect(state => ({ me: state.formOne }), actions)(FormOne);在上面的例子FormOne中只是监听自己的状态更新;然而,使用上下文而不是 Redux 的类似逻辑将导致上下文提供者包装的整个组件树更新(包括父组件和兄弟组件):import React, { useContext } from 'react';// Custom componentimport { InputField } from 'shared';// Custom context - below component must be wrapped with the providerimport { FormContext } from 'context';const FormTwo = () => {&nbsp; const context = useContext(FormContext);&nbsp; return(&nbsp; &nbsp; <form>&nbsp; &nbsp; &nbsp; <InputField&nbsp; &nbsp; &nbsp; &nbsp; inputId="f2f1"&nbsp; &nbsp; &nbsp; &nbsp; label="field one"&nbsp; &nbsp; &nbsp; &nbsp; value={context.state.formTwo.fieldOne}&nbsp; &nbsp; &nbsp; &nbsp; onChange={(e) => context.setFormTwoFieldOne(e.target.value)}&nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; <InputField&nbsp; &nbsp; &nbsp; &nbsp; inputId="f2f2"&nbsp; &nbsp; &nbsp; &nbsp; label="field two"&nbsp; &nbsp; &nbsp; &nbsp; value={context.state.formTwo.fieldTwo}&nbsp; &nbsp; &nbsp; &nbsp; onChange={(e) => context.setFormTwoFieldTwo(e.target.value)}&nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; <InputField&nbsp; &nbsp; &nbsp; &nbsp; inputId="f2f3"&nbsp; &nbsp; &nbsp; &nbsp; label="field three"&nbsp; &nbsp; &nbsp; &nbsp; value={context.state.formTwo.fieldThree}&nbsp; &nbsp; &nbsp; &nbsp; onChange={(e) => context.setFormTwoFieldThree(e.target.value)}&nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; </form>&nbsp; );};export default FormTwo;可以对上述两个组件进行一些改进,但它们旨在作为如何将子组件连接到提升状态的示例。也可以使用 连接到单个父组件props,但这是效率最低的选项,并且会使您的体系结构混乱。关键要点:将 Redux 用于您的用例。如果正确实施,这是最有效的选择。

元芳怎么了

提升状态确实是这样做的正确方法。要优化子部分,您可以使用PureComponent ==>&nbsp;https://reactjs.org/docs/react-api.html#reactpurecomponentAKA 记忆组件 ==>&nbsp;https://reactjs.org/docs/react-api.html#reactmemoReact.memo 是一个高阶组件。它类似于 React.PureComponent 但用于函数组件而不是类。此外,如果您在钩子宇宙结帐中useCallback :https ://reactjs.org/docs/hooks-reference.html#usecallback使用备忘录: https&nbsp;://reactjs.org/docs/hooks-reference.html#usememo如果您有任何机会使用 Redux,请记得查看重新选择:https ://github.com/reduxjs/reselect

Cats萌萌

将所有表单包装在一个仅处理保存所有表单数据并运行“全部保存”功能的组件中:包装器组件应该有一个包含所有表单数据的状态,它应该看起来像这样:class Wrapper Component extends React.Component {&nbsp; constructor(props) {&nbsp; &nbsp; super(props);&nbsp; &nbsp; this.state = {&nbsp; &nbsp; &nbsp; formsData: {},&nbsp; &nbsp; };&nbsp; }}formsData 的结构应该差不多是这样的: { 0: { title:"text", type:"video", etc:"etc" }, 1: { title:"text", type:"video", etc: "etc" }} 键(0,1 等)代表表单 ID,并且可以设置为每个 for 具有的任何唯一修饰符。然后让包装器组件处理每个单独表单的 onChange -> 每个单独表单上的每次更改都应该提升新状态(新更新的数据)并相应地更新 formsData 状态 obj:const onChange(formData) {&nbsp; &nbsp;const formattedData = {[formData.id]: {...formData}}&nbsp; &nbsp;this.setState({formsData: {...formsData, ...formattedData}})}* 这只是一个例子,在每个表单的每次更改中,您都会提升整个数据对象,您可以通过多种方式进行操作比,保存所有按钮也应该在包装器组件中处理,并将您使用它存储的所有数据提升到父组件中的相关功能/自行处理。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript