Como usar crianças com React Stateless Functional Component no TypeScript?

88

Usando o TypeScript com React, não precisamos mais estender React.Propspara que o compilador saiba que todos os adereços do componente react podem ter filhos:

interface MyProps { }

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

No entanto, não parece ser o caso para componentes funcionais sem estado:

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

Emite o erro de compilação:

Erro: (102, 17) TS2339: A propriedade 'filhos' não existe no tipo 'MyProps'.

Acho que é porque realmente não há como o compilador saber que uma função vanilla será fornecida childrenno argumento props.

Portanto, a questão é como devemos usar filhos em um componente funcional sem estado no TypeScript?

Eu poderia voltar ao modo antigo MyProps extends React.Props, mas a Propsinterface está marcada como obsoleta e os componentes sem estado não têm ou suportam um, Props.refconforme eu o entendo.

Então, eu poderia definir o childrenadereço manualmente:

interface MyProps {
  children?: React.ReactNode;
}

Primeiro: é ReactNodeo tipo correto?

Segundo: tenho que escrever filhos como opcionais ( ?) ou então os consumidores pensarão que isso childrené um atributo do componente ( <MyStatelessComponent children={} />) e gerarão um erro se não for fornecido com um valor.

Parece que estou faltando alguma coisa. Alguém pode esclarecer se meu último exemplo é a maneira de usar componentes funcionais sem estado com crianças no React?

Aaron Beall
fonte

Respostas:

89

Atualização do React 16.8: Desde o React 16.8, os nomes React.SFCe React.StatelessComponentestão obsoletos. Na verdade, eles se tornaram apelidos para React.FunctionComponenttipo ou React.FCabreviatura.

Você os usaria da mesma maneira:

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

Antes de reagir 16.8 (mais antigos):

Por enquanto, você pode usar o React.StatelessComponent<>tipo, como:

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

O que eu adicionei lá é definir o tipo de retorno do componente para React.StatelessComponenttipo.

Para um componente com seus próprios adereços personalizados (como MyPropsinterface):

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

Agora, propsobteve a childrenpropriedade, bem como as da MyPropsinterface.

Eu verifiquei isso na versão datilografada 2.0.7

Além disso, você pode usar em React.SFCvez de React.StatelessComponentpara abreviar.

Leone
fonte
Obrigado! Parece que estou em uma versão antiga das tipificações que não suportam isso ... Acho que é hora de morder a bala e usar TS 2.0 com@types
Aaron Beall
3
React.StatelessComponent/ React.SFCestão obsoletos. Em React.FunctionComponentvez disso, é recomendável consultar .
Alexander Kachkaev
Observe que este método não funciona se você tiver um componente genérico
FunkeyFlo
94

Você pode usar o React.PropsWithChildren<P>tipo para seus adereços:

interface MyProps { }

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

Você pode usar

interface YourProps { }
const yourComponent: React.SFC<YourProps> = props => {}
Jun Yin
fonte
React.SFCestá obsoleto
Arjan
0

Resposta mais simples: Use ReactNode:

interface MyProps {
  children?: React.ReactNode
}

Se childrené opcional ou não (ou seja, ter ?ou não) depende do seu componente. Essa ?é a maneira mais concisa de expressar isso, então nada de errado com isso.

No histórico: esta não era necessariamente a resposta correta quando perguntado originalmente: o tipo ReactNodefoi adicionado em (quase) sua forma atual em março de 2017 apenas por esta solicitação de pull , mas quase todos que estão lendo isso hoje devem estar em uma versão moderna do React .

Por último, sobre passar childrencomo "atributo" (que, no jargão do React, seria passar como "prop", não atributo): É possível, mas na maioria dos casos é melhor ler ao passar filhos JSX:

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

lê mais facilmente do que

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

Você pode apenas adicionar filhos ao componente e se ele estiver conectado a um contêiner, isso é tudo que você precisa.

const MyComponent = ({ 
   children  
}) => {
  return <div>{children}</div>

}
NS Niko
fonte
Por que adicionar outra resposta a uma pergunta tão antiga?
Mike Szyndel
E era uma pergunta do TypeScript.
Zsolt Meszaros