为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

HUX布斯 2022-01-13 15:17:46
我有一个父组件,它具有称为脚本的基本数据,它有多个序列,每个序列由多个项目(输入、下拉列表、...)组成。现在我需要在父级中更新数据,因为我想放置一个保存按钮,该按钮将一键保存所有表单。它看起来像这样:我尝试了两种处理方式:每个孩子都有一个 onChange 属性,在该属性中,父母使用新数据设置状态。但这里的问题是,由于这是一个相当复杂的表单,它每次都会重新渲染所有内容,因此在输入输入时会有明显的延迟。仅仅改变一个孩子的道具对象的“坏”,这很快,但我知道这是一种不好的做法。在这样的规模上处理表格的最佳方法是什么?是否应该以不同的方式设置?
查看完整描述

3 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

这是我花了一些时间与自己斗争的问题。有多种方法可以将子状态保持在更高级别;但是,我发现在您的特定情况下,通常最好使用 Redux。


需要明确的是,我通常不惜一切代价避免 Redux(支持 React 的上下文),但 Redux 让您能够订阅子组件中的特定状态。当您只需要更新一个子组件时,侦听子组件中的一个状态将阻止您的父组件和兄弟组件更新。这在一次处理多个表单时效率更高。


例如,以下组件将仅侦听影响其自身状态的状态更新。这些更新将绕过表单父组件和兄弟组件:


import React from 'react';

import { connect } from 'react-redux';

import * as actions from 'redux/actions';

// Custom component

import { InputField } from 'shared';


const FormOne = ({ me, actions }) => (

  <form>

    <InputField

      inputId="f1f1"

      label="field one"

      value={me.fieldOne}

      onChange={(e) => actions.setFormOneFieldOne(e.target.value)}

    />

    <InputField

      inputId="f1f2"

      label="field two"

      value={me.fieldTwo}

      onChange={(e) => actions.setFormOneFieldTwo(e.target.value)}

    />

    <InputField

      inputId="f1f3"

      label="field three"

      value={me.fieldThree}

      onChange={(e) => actions.setFormOneFieldThree(e.target.value)}

    />

  </form>

);


export default connect(state => ({ me: state.formOne }), actions)(FormOne);

在上面的例子FormOne中只是监听自己的状态更新;然而,使用上下文而不是 Redux 的类似逻辑将导致上下文提供者包装的整个组件树更新(包括父组件和兄弟组件):


import React, { useContext } from 'react';

// Custom component

import { InputField } from 'shared';

// Custom context - below component must be wrapped with the provider

import { FormContext } from 'context';



const FormTwo = () => {

  const context = useContext(FormContext);


  return(

    <form>

      <InputField

        inputId="f2f1"

        label="field one"

        value={context.state.formTwo.fieldOne}

        onChange={(e) => context.setFormTwoFieldOne(e.target.value)}

      />

      <InputField

        inputId="f2f2"

        label="field two"

        value={context.state.formTwo.fieldTwo}

        onChange={(e) => context.setFormTwoFieldTwo(e.target.value)}

      />

      <InputField

        inputId="f2f3"

        label="field three"

        value={context.state.formTwo.fieldThree}

        onChange={(e) => context.setFormTwoFieldThree(e.target.value)}

      />

    </form>

  );

};


export default FormTwo;

可以对上述两个组件进行一些改进,但它们旨在作为如何将子组件连接到提升状态的示例。也可以使用 连接到单个父组件props,但这是效率最低的选项,并且会使您的体系结构混乱。


关键要点:将 Redux 用于您的用例。如果正确实施,这是最有效的选择。


查看完整回答
反对 回复 2022-01-13
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

提升状态确实是这样做的正确方法。要优化子部分,您可以使用

React.memo 是一个高阶组件。它类似于 React.PureComponent 但用于函数组件而不是类。

此外,如果您在钩子宇宙结帐中

如果您有任何机会使用 Redux,请记得查看


查看完整回答
反对 回复 2022-01-13
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

将所有表单包装在一个仅处理保存所有表单数据并运行“全部保存”功能的组件中:


包装器组件应该有一个包含所有表单数据的状态,它应该看起来像这样:


class Wrapper Component extends React.Component {

  constructor(props) {

    super(props);

    this.state = {

      formsData: {},

    };

  }

}

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

   const formattedData = {[formData.id]: {...formData}}

   this.setState({formsData: {...formsData, ...formattedData}})

}

* 这只是一个例子,在每个表单的每次更改中,您都会提升整个数据对象,您可以通过多种方式进行操作


比,保存所有按钮也应该在包装器组件中处理,并将您使用它存储的所有数据提升到父组件中的相关功能/自行处理。


查看完整回答
反对 回复 2022-01-13
  • 3 回答
  • 0 关注
  • 232 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信