reactjs - Bruke HOCs på generiske Typescript React-komponenter


Jeg har en React-komponent som er typet med en generisk. Den komponenten blir videre utvidet med en høyere ordens komponent (i dette tilfellet, redux-form). Her er en nedstrippet versjon av klassen min og HOC-en som blir brukt:

import * as React from "react";

interface MyFormProps<D> {
    prop: D;
    form: string;
}

class MyForm<D> extends React.Component<MyFormProps<D>, {}> {
    render(): JSX.Element {
        return (
            <form>
                {this.props.prop}
            </form>
        );
    }
}

export const ConnectedMyForm = reduxForm({} as Config<any, {}, {}>)(MyForm);

Deretter prøver jeg å lage en skrevet versjon av komponenten min i en annen komponent.

import { ConnectedMyForm } from "./my-form";

interface FormType {
    // Form props here
}

type TypedForm = new () => ConnectedMyForm<FormType>;
const TypedForm = ConnectedMyForm as TypedForm;

For å kunne bruke det i TSX som følger:

<TypedForm />

Denne metoden fungerer helt fint på en annen komponent jeg har laget som ikke har HOC brukt, men her får jeg følgende feil:

feil TS2304: Kan ikke finne navnet 'ConnectedMyForm'.

på linjen type TypedForm=new() => ConnectedMyForm<FormType>;.

Dette skjer bare når jeg bruker HOC-funksjonen på komponenten min. Jeg antar det er fordi jeg ikke har spesifisert den generiske typingen på den tilkoblede versjonen av skjemaet. Men hvordan ville jeg spesifisert den typingen?

Svar #1

Hvorfor ikke bare lage en hoc/EnhancedForm som:

import * as React from 'react';

interface EnhancedProps {
    name: string;
}

export default <T extends {}>(Component: React.StatelessComponent<T> | React.ComponentClass<T>):
    React.StatelessComponent<T & EnhancedProps> =>
    (props: T & EnhancedProps) => {
        return <Component { ...props } />
    }

Og så bruk bare den HoC i din SimpleForm som:

const SimpleForm = props => {

  const handleSubmit = () => { alert("Validated"); }

  const { pristine, reset, submitting } = props
  return (
    <form onSubmit={ handleSubmit }>
      <div>
        <label>First Name</label>
        ....
    </form>
  )
}

export default EnhancedForm(reduxForm({
  form: 'simple' // a unique identifier for this form
})(SimpleForm))

Og til slutt bruk det slik du beskriver:

render() {
    return (
      <SimpleForm name="SimpleName" />
    );
  }

Relaterte artikler