¿Cómo usar niños con React Stateless Functional Component en TypeScript?

85

Al usar TypeScript con React, ya no tenemos que extendernos React.Propspara que el compilador sepa que todos los accesorios de los componentes react pueden tener hijos:

interface MyProps { }

class MyComponent extends React.Component<MyProps, {}> {
  public render(): JSX.Element {
    return <div>{this.props.children}</div>;
  }
}

Sin embargo, no parece ser el caso de los componentes funcionales sin estado:

const MyStatelessComponent = (props: MyProps) => {
  return (
    <div>{props.children}</div>
  );
};

Emite el error de compilación:

Error: (102, 17) TS2339: La propiedad 'children' no existe en el tipo 'MyProps'.

Supongo que esto se debe a que realmente no hay forma de que el compilador sepa que se va a dar una función de vainilla childrenen el argumento props.

Entonces, la pregunta es ¿cómo deberíamos usar los niños en un componente funcional sin estado en TypeScript?

Podría volver a la forma anterior de MyProps extends React.Props, pero la Propsinterfaz está marcada como obsoleta y los componentes sin estado no tienen ni admiten una Props.refcomo yo la entiendo.

Entonces podría definir el childrenaccesorio manualmente:

interface MyProps {
  children?: React.ReactNode;
}

Primero: ¿es ReactNodeel tipo correcto?

Segundo: tengo que escribir child como opcional ( ?) o los consumidores pensarán que childrense supone que es un atributo del componente ( <MyStatelessComponent children={} />) y generarán un error si no se les proporciona un valor.

Parece que me falta algo. ¿Alguien puede proporcionar algo de claridad sobre si mi último ejemplo es la forma de usar componentes funcionales sin estado con niños en React?

Aaron Beall
fuente

Respuestas:

82

Actualización de React 16.8: desde React 16.8, los nombres React.SFCy React.StatelessComponentestán en desuso. En realidad, se han convertido en alias de React.FunctionComponenttipo o React.FCabreviatura.

Sin embargo, los usaría de la misma manera:

const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Antes de React 16.8 (más antiguo):

Por ahora, puede usar el React.StatelessComponent<>tipo, como:

const MyStatelessComponent : React.StatelessComponent<{}> = props =>
    <div>{props.children}</div>

Lo que he agregado allí es configurar el tipo de retorno del componente a React.StatelessComponentescribir.

Para un componente con sus propios accesorios personalizados (como MyPropsinterfaz):

const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Ahora, propstiene la childrenpropiedad y las de MyPropsinterface.

Verifiqué esto en la versión 2.0.7 de mecanografiado

Además, puede utilizar en React.SFClugar de React.StatelessComponentpor brevedad.

Leona
fuente
¡Gracias! Parece que estoy en una versión antigua de la mecanografía que no admite esto ... Supongo que es hora de morder la bala y usar TS 2.0 con@types
Aaron Beall
2
React.StatelessComponent/ React.SFCestán en desuso. Se recomienda consultar en su React.FunctionComponentlugar.
Alexander Kachkaev
Tenga en cuenta que este método no funciona si tiene un componente genérico
FunkeyFlo
93

Puedes usar React.PropsWithChildren<P>tipografía para tus accesorios:

interface MyProps { }

function MyComponent(props: React.PropsWithChildren<MyProps>) {
  return <div>{props.children}</div>;
}
baitun
fuente
0

Puedes usar

interface YourProps { }
const yourComponent: React.SFC<YourProps> = props => {}
Jun Yin
fuente
0

Respuesta más simple: Utilice ReactNode:

interface MyProps {
  children?: React.ReactNode
}

Si childrenes opcional o no (es decir, tener ?o no) depende de su componente. El ?es la forma más concisa para expresar que, de manera equivocada nada con eso.

Sobre el historial: esta no era necesariamente la respuesta correcta cuando se preguntó originalmente: el tipo ReactNodese agregó en (casi) su forma actual en marzo de 2017 solo mediante esta solicitud de extracción , pero casi todos los que lean esto hoy deberían estar en una versión lo suficientemente moderna de React .

Por último, sobre pasar childrencomo "atributo" (que, en la jerga de React, sería pasarlo como "prop", no como atributo): es posible, pero en la mayoría de los casos se lee mejor cuando se pasan los niños JSX

<MyComponent>
  <p>This is part of the children.</p>
</MyComponent>

lee más fácilmente que

<MyComponent children={<p>This is part of the children.</p>} />
chris6953
fuente