簡體   English   中英

從多個復雜子組件獲取值的最佳方式?

[英]Best way to get values from multiple complex child components?

我有一個父組件,它有稱為腳本的基本數據,它有多個序列,每個序列由多個項目(輸入、下拉列表、...)組成。

現在我需要父級中的更新數據,因為我想放置一個保存按鈕,只需單擊一下即可保存所有表單。

它看起來像這樣:

例子

我嘗試了兩種處理方法:

  • 每個孩子都有一個 onChange 屬性,其中父級使用新數據設置狀態。 但這里的問題是,由於這是一個相當復雜的表單,它每次都會重新呈現所有內容,因此在輸入時會出現明顯的延遲。
  • 只是改變孩子的道具對象的“壞”,這很快,但我知道這是一種不好的做法。

處理這種規模的表格的最佳方法是什么? 應該設置不同嗎?

提升狀態確實是正確的做法。 要優化子部分,您可以使用

React.memo 是一個高階組件。 它類似於 React.PureComponent 但用於功能組件而不是類。

另外,如果您在 hooks universe checkout 中

  • useCallback: https ://reactjs.org/docs/hooks-reference.html#usecallback
  • 使用備忘錄: https ://reactjs.org/docs/hooks-reference.html#usememo

如果您有機會使用 Redux,請記得查看

  • 重新選擇: https ://github.com/reduxjs/reselect

將所有表單包裝在一個僅處理保存所有表單數據和運行“全部保存”功能的組件中:

包裝組件應該有一個包含所有表單數據的狀態,它應該看起來像這樣:

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,並且可以設置為每個具有的任何唯一修飾符。

然后讓包裝器組件處理每個單獨表單的 onChange -> 每個單獨表單上的每個更改都應該提升新狀態(新更新數據)並相應地更新 formsData 狀態對象:

const onChange(formData) {
   const formattedData = {[formData.id]: {...formData}}
   this.setState({formsData: {...formsData, ...formattedData}})
}

* 這只是一個例子,在每個表單的每個更改中,你提升了整個數據對象,你可以通過多種方式做到這一點

然后,保存所有按鈕也應該在包裝器組件中處理,並將您存儲的所有數據提升到父組件中的相關功能/自行處理。

祝你好運!

這是我花了一些時間與自己斗爭的問題。 有多種方法可以在更高級別維護子狀態; 但是,我發現在您的特定情況下,通常最好使用 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 用於您的用例。 如果正確實施,這是最有效的選擇。

祝你好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM