reactjs - Hur man skickar resten av props till en react-komponent samtidigt som man har definierade nödvändiga props i ett interface


Så är detta samma problem, eller missar jag bara något?

import * as React from 'react';

interface Props {
    value: string;
}

const MyComponent = (props: Props) => {
    const { value, ...rest } = props;

    return (
        <input {...rest} type="text" value={value} />
    );
}

interface ParentState {
    searchText: string;
}

class ParentComponent extends React.Component<{}, ParentState> {
    state: ParentState = {
        searchText: ''
    };

    onSearchTextChanged = (e: React.FormEvent<HTMLInputElement>) => {
        this.setState({
            searchText: e.currentTarget.value
        });
    }

    render() {
        const { searchText } = this.state;

        return (
            <div>
                <h2>Some Text</h2>
                <MyComponent value={searchText} onChange={this.onSearchTextChanged} className="search-input" placeholder="Enter text"/> 
// Errors here
            </div>
        )
    }
}

export default ParentComponent

När jag har mina props för MyComponent definierade i ett gränssnitt får jag följande fel:

fel TS2339: Egenskapen 'onChange' finns inte på typen 'IntrinsicAttributes & Props'.

Men om jag ändrar props-typen till any, kompilerar det utan problem.

const MyComponent = (props: any) => {

Är det möjligt att definiera props i ett interface så att det finns specifika props som är obligatoriska, men också tillåta att ytterligare props skickas in så att jag inte behöver lägga till dem uttryckligen i interfacet?

Jag använder TypeScript 2.3.4 och React 15.5.4.

Svar #1

Om du vill vidarebefordra alla egenskaper hos input-elementet inuti MyComponent till props för MyComponent kan du slå upp vilka props input har (i VSCode till exempel, använd gå till definition medan du är på input-taggen).

interface IntrinsicElements {
   ....
   input: React.DetailedHTMLProps<React.InputHTMLAttributes<>, HTMLInputElement>;
   ....
}

Vi kan använda React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> som basklass för våra props och vi får alla egenskaper hos input. Eftersom DetailedHTMLProps bara lägger till ref till React.InputHTMLAttributes<HTMLInputElement> kan vi bara använda React.InputHTMLAttributes<HTMLInputElement> som basgränssnitt för att få alla input-egenskaper utom ref:

import * as React from 'react'

interface Props extends React.InputHTMLAttributes<HTMLInputElement> {
    value: string;
}

const MyComponent = (props: Props) => {
    const { value, ...rest } = props;

    return (
        <input {...rest} type="text" value={value} />
    );
}

// Usage
interface ParentState  { searchText :string }
class ParentComponent extends React.Component<{}, ParentState> {
  state: ParentState = {
      searchText: ''
  };

  onSearchTextChanged = (e: React.FormEvent<HTMLInputElement>) => {
      this.setState({
          searchText: e.currentTarget.value
      });
  }

  render() {
      const { searchText } = this.state;

      return (
          <div>
              <h2>Some Text</h2>
              <MyComponent value={searchText} onChange={this.onSearchTextChanged} className="search-input" placeholder="Enter text"/> 
          </div>
      )
  }
}

export default ParentComponent

Svar #2

Du kan undvika överflödiga egenskaps-/attributkontroller genom att lägga till en strengindexsignatur till ditt gränssnitt:

interface Props {
    value: string;

    // This is a string index signature.
    // This means that all properties in 'Props' are assignable to
    // the empty object type ({})
    [propName: string]: {};
}

Du skulle också kunna skriva [propName: string]: any, men det gör det generellt sett mindre säkert att använda i MyComponent själv.

Relaterade artiklar