簡體   English   中英

將泛型類型的實現傳遞給React組件prop

[英]Passing implementations of generic types to React component props

我正在研究TypeScript / React項目,我們正在為多步過程構建一個通用的“向導”組件。 該向導是一個包裝器,它接受“面板”組件屬性的數組,並通過IWizardPanelProps接口向每個組件公開導航邏輯。

向導組件和面板界面的實現如下:

export interface IWizardPanelProps {
  changePanel: (increment: number) => void;
}

export class WizardPanel<T> extends React.Component<IWizardPanelProps & T>{
  constructor(props: IWizardPanelProps & T) {
    super(props);
  }
}

interface IWizardProps {
  panelComponents: (typeof WizardPanel)[],
  showControls?: boolean // Hidden by default - assumes panels themselves handle pagination
}

interface IWizardState {
  panelIndex: number
}

export class Wizard extends React.Component<IWizardProps, IWizardState> {
  constructor(props: IWizardProps) {
    super(props);

    this.state = {
      panelIndex: 0
    }
  }

  changePanel = (increment: number) => {
    const newIndex = this.state.panelIndex + increment;

    this.setState({ panelIndex: newIndex });
  };

  render() {
    const { panelComponents, showControls } = this.props;

    return (
      <div>
        <p><strong>Ye olde Wizard Component! (This is a placeholder, but the functionality is mostly there)</strong></p>
        {panelComponents.map((Panel, key) => (
          <div className={key === this.state.panelIndex ? undefined : 'hidden'} key={key}>{<Panel {...this.props} changePanel={this.changePanel}></Panel>}</div>
        ))}
        {showControls && <div>
            <button disabled={this.state.panelIndex === 0} onClick={() => this.changePanel(-1)}>
            Previous
          </button>
          <button disabled={this.state.panelIndex === panelComponents.length - 1} onClick={() => this.changePanel(1)}>
            Next
          </button>
        </div>}
      </div>
    );  
  }
}

然后,當我們創建面板組件時,我們會像這樣:

interface IMyPanelProps {
  ...
}


export class MyPanel extends WizardPanel<IMyPanelProps> {
  constructor(props: IWizardPanelProps & IMyPanelProps) {
    super(props);
  }
  render() {
    ...
  }
  ...
}

到目前為止還好嗎?

但是,當我們去實現這樣的向導時:

<Wizard panelComponents={[ MyPanel ]}></Wizard>

我們收到以下錯誤:

類型'(typeof MyPanel)[]'不能分配給類型'(typeof WizardPanel)[]'。

類型'typeof MyPanel'不能分配給類型'typeof WizardPanel'。

類型“ MyPanel”不可分配給類型“ WizardPanel”。

屬性“ props”的類型不兼容。

輸入'Readonly <{children ?: ReactNode; }>&Readonly <IWizardPanelProps&IMyPanelProps>'不可分配為類型'Readonly <{children ?: ReactNode; }>和Readonly <IWizardPanelProps&T>'。

輸入'Readonly <{children ?: ReactNode; }>&Readonly <IWizardPanelProps&IMyPanelProps>”不能分配為類型“ Readonly <IWizardPanelProps&T>”。

是什么賦予了? 似乎可以歸結到最后一行:

Readonly<{ children?: ReactNode; }> & Readonly< IWizardPanelProps & IMyPanelProps>' is not assignable to type 'Readonly< IWizardPanelProps & T>

但我不明白自己做錯了什么。 我們如何錯過Readonly<{ children?: ReactNode; }> Readonly<{ children?: ReactNode; }>在propComponents的IWizardProps聲明中?

您可以使用React.ComponentType類型。 這是定義組件類型的預期方式。

interface IWizardProps {
    panelComponents: React.ComponentType<IWizardPanelProps>)[],
    showControls?: boolean 
}

問題在於WizardPanel是泛型的,而分配的類卻不是,這會導致類型之間的不兼容。 例如,這也可以工作:

export class BasicWizardPanel extends WizardPanel<{}>{}

interface IWizardProps {
    panelComponents: (typeof BasicWizardPanel)[],
    showControls?: boolean // Hidden by default - assumes panels themselves handle pagination
}

暫無
暫無

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

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