├── CONTRIBUTING.md ├── GLOSSARY.md ├── LICENSE └── README.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Então você quer contribuir! 2 | 3 | Obrigado por ajudar a comunidade! Nós estamos constantemente buscando por contribuidores e mantenedores então você é mais do que bem-vindo. 4 | 5 | Eu pensei em estipular alguns princípios básicos que nós iremos seguir para evitar que este repositório se torne muito confuso e perca seu valor. 6 | 7 | 1. **Nós somos uma CHEATSHEET antes de tudo**: Todos os exemplos devem ser o mais simples possível, fáceis de encontrar, e apresentáveis para copiar-e-colar. 8 | 2. **Explicações claras**: Nada além de 1 ou 2 sentenças de explicação, mais do que isso incluímos a tag `detalhes`. 9 | 3. **SOMENTE React + TypeScript**: React possui um imenso ecossistema e é impossível cobri-lo completamente. Isto inclui Redux. Sugiro ás pessoas a manter listas separadas para coisas como React + Apollo Graphql, por exemplo. Nós também não tentamos convencer ninguém a usar TypeScript, estamos aqui para ajudar as pessoas que já decidiram experimentá-lo. 10 | 4. **Inclua links para o sandbox do Typescript**: Sempre que adicionar um exemplo de código com mais de quatro linhas, adicione um link para o sandbox com o código em Typescript. Use as opções padrão do compilador. 11 | 12 | E é isso! Outra vez, estamos muito felizes que você esteja pensando em ajudar e, quem sabe, a pessoa que você está ajudando pode ser você mesma no futuro! 13 | 14 | ## Estrutura do projeto 15 | 16 | - O conteúdo completo está em `/docs` 17 | - O `/docs/basic` é compilado no `README.md` para preservar a legibilidade do GitHub por meio de GitHub actions, obrigado 18 | - `/website` consome o conteúdo de `/docs`, que é um site [Docusaurus 2](https://docusaurus.io/), que possui o sistema de [busca Algolia](https://www.algolia.com/) (obrigado a ambas as equipes pelo apoio!) 19 | 20 | O site está hospedado no Netlify, na conta pessoal do swyx. 21 | 22 | Para rodar o docsite localmente: 23 | 24 | ```bash 25 | yarn # instala as dependências 26 | ## garanta que as dependências também sejam instaladas em /website 27 | cd website && yarn start 28 | ``` 29 | 30 | exemplo de instalação bem-sucedida 31 | 32 | ``` 33 | yarn run v1.22.4 34 | warning package.json: No license field 35 | $ docusaurus start 36 | Starting the development server... 37 | 38 | ✔ Client 39 | Compiled successfully in 9.61s 40 | 41 | ℹ 「wds」: Project is running at http://localhost:3000/ 42 | ℹ 「wds」: webpack output is served from / 43 | ℹ 「wds」: Content not from webpack is served from /Users/wanshawn/Work/react-typescript-cheatsheet/website 44 | ℹ 「wds」: 404s will fallback to /index.html 45 | 46 | ✔ Client 47 | Compiled successfully in 116.41ms 48 | ``` 49 | -------------------------------------------------------------------------------- /GLOSSARY.md: -------------------------------------------------------------------------------- 1 | # Guia de Estilo Universal 2 | 3 | ## Texto em Blocos de Código 4 | 5 | Mantenha o texto em blocos de código sem tradução, exceto para os comentários. Você pode optar por traduzir o texto em strings, mas tenha cuidado para não traduzir strings que se refiram ao código! 6 | 7 | Exemplo: 8 | 9 | ```js 10 | // Example 11 | const element =

Hello, world

; 12 | ReactDOM.render(element, document.getElementById('root')); 13 | ``` 14 | 15 | ✅ FAÇA: 16 | 17 | ```js 18 | // Exemplo 19 | const element =

Hello, world

; 20 | ReactDOM.render(element, document.getElementById('root')); 21 | ``` 22 | 23 | ✅ PERMITIDO: 24 | 25 | ```js 26 | // Exemplo 27 | const element =

Olá mundo

; 28 | ReactDOM.render(element, document.getElementById('root')); 29 | ``` 30 | 31 | ❌ NÃO FAÇA: 32 | 33 | ```js 34 | // Exemplo 35 | const element =

Olá mundo

; 36 | // "root" se refere a um ID de elemento. 37 | // NÃO TRADUZA 38 | ReactDOM.render(element, document.getElementById('raiz')); 39 | ``` 40 | 41 | ❌ DEFINITIVAMENTE NÃO FAÇA: 42 | 43 | ```js 44 | // Exemplo 45 | const elemento =

Olá mundo

; 46 | ReactDOM.renderizar(elemento, documento.obterElementoPorId('raiz')); 47 | ``` 48 | 49 | ## Links Externos 50 | 51 | Se um link externo se referir a um artigo no [MDN] or [Wikipedia] e se houver uma versão traduzida em seu idioma em uma qualidade decente, opte por usar a versão traduzida. 52 | 53 | [mdn]: https://developer.mozilla.org/pt-BR/ 54 | [wikipedia]: https://pt.wikipedia.org/wiki/Wikipédia:Página_principal 55 | 56 | Exemplo: 57 | 58 | ```md 59 | React elements are [immutable](https://en.wikipedia.org/wiki/Immutable_object). 60 | ``` 61 | 62 | ✅ OK: 63 | 64 | ```md 65 | Elementos React são [imutáveis](https://pt.wikipedia.org/wiki/Objeto_imutável). 66 | ``` 67 | 68 | Para links que não possuem tradução (Stack Overflow, vídeos do YouTube, etc.), simplesmente use o link original. 69 | 70 | ## Traduções Comuns 71 | 72 | Sugestões de palavras e termos: 73 | 74 | | Palavra/Termo original | Sugestão | 75 | | ---------------------- | -------------------------------------- | 76 | | assertion | asserção | 77 | | browser | navegador | 78 | | bubbling | propagar | 79 | | bug | erro | 80 | | class component | componente de classe | 81 | | class | classe | 82 | | client | cliente | 83 | | client-side | lado do cliente | 84 | | container | contêiner | 85 | | context | contexto | 86 | | controlled component | componente controlado | 87 | | debugging | depuração | 88 | | DOM node | nó do DOM | 89 | | event handler | manipulador de eventos (event handler) | 90 | | function component | componente de função | 91 | | handler | manipulador | 92 | | helper function | função auxiliar | 93 | | high-order components | componente de alta-ordem | 94 | | key | chave | 95 | | library | biblioteca | 96 | | lowercase | minúscula(s) / caixa baixa | 97 | | package | pacote | 98 | | React element | Elemento React | 99 | | React fragment | Fragmento React | 100 | | render | renderizar (verb), renderizado (noun) | 101 | | server | servidor | 102 | | server-side | lado do servidor | 103 | | siblings | irmãos | 104 | | stateful component | componente com estado | 105 | | stateful logic | lógica com estado | 106 | | to assert | afirmar | 107 | | to wrap | encapsular | 108 | | uncontrolled component | componente não controlado | 109 | | uppercase | maiúscula(s) / caixa alta | 110 | 111 | ## Conteúdo que não deve ser traduzido 112 | 113 | - array 114 | - arrow function 115 | - bind 116 | - bundle 117 | - bundler 118 | - callback 119 | - camelCase 120 | - DOM 121 | - event listener 122 | - framework 123 | - hook 124 | - log 125 | - mock 126 | - portal 127 | - props 128 | - ref 129 | - release 130 | - script 131 | - single-page-apps 132 | - state 133 | - string 134 | - string literal 135 | - subscribe 136 | - subscription 137 | - template literal 138 | - timestamps 139 | - UI 140 | - watcher 141 | - widgets 142 | - wrapper 143 | 144 | Se deseja agregar algo que falta, abra um [issue](https://github.com/typescript-cheatsheets/react-pt/issues/new). 145 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 TypeScript Cheatsheets 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

React+TypeScript Cheatsheets em Português

3 | 4 | 5 | react + ts logo 12 | 13 | 14 |

Cheatsheets para desenvolvedores com experiência em React que estão iniciando com TypeScript

15 | 16 | [**Web docs**](https://react-typescript-cheatsheet.netlify.app/docs/basic/setup) | 17 | [中文翻译](https://github.com/fi3ework/blog/tree/master/react-typescript-cheatsheet-cn) | 18 | [**Español**](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet-es) | 19 | [Contribute!](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/blob/master/CONTRIBUTING.md) | 20 | [Ask!](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new/choose) 21 | 22 |
23 | 24 | --- 25 | 26 |
27 | 28 | :wave: Este repositório é mantido por [@giseladifini](https://twitter.com/GiselaDifini) e [@swyx](https://twitter.com/swyx). Estamos muito felizes que você quer experimentar React com Typescript! 29 | Se você perceber algo de errado ou faltando, por favor abra uma [issue](https://github.com/typescript-cheatsheets/react-pt/issues/new)! :+1: 30 | 31 |
32 | 33 | --- 34 | 35 | ## Todas as dicas de React + TypeScript 36 | 37 | - **Cheatsheet Básico** ([`/README.md`](/README.md#basic-cheatsheet-table-of-contents)) é focado em ajudar desenvolvedores React a começar a usar TS com React **apps** 38 | - Foco nas melhores práticas com exemplos para copiar e colar. 39 | - Explica alguns tipos básicos de uso de TS e configuração ao longo do caminho. 40 | - Responde às perguntas mais frequentes. 41 | - Não cobre a lógica de tipo genérico em detalhes. Em vez disso, preferimos ensinar técnicas de solução de problemas simples para iniciantes. 42 | - O objetivo é se familiarizar com TS sem precisar aprender _muito_ sobre TS. 43 | - **Cheatsheet Avançado** ([`/AVANÇADO.md`](https://react-typescript-cheatsheet.netlify.app/docs/advanced)) ajuda a mostrar e explicar o uso avançado de tipos genéricos para pessoas que escrevem utilitários/funções/props de renderização/componentes de ordem superior (HOCs) reutilizáveis ​​e **bibliotecas** TS+React. 44 | - Possui dicas e truques diversos para usuários profissionais. 45 | - Conselhos para contribuir com DefinitelyTyped. 46 | - O Objetivo é tirar _total vantagem_ sobre o TypeScript. 47 | - **Cheatsheet de migração** ([`/MIGRANDO.md`](https://react-typescript-cheatsheet.netlify.app/docs/migration)) ajuda a reunir conselhos para a migração incremental de grandes bases de código de JS ou Flow, **de pessoas que já fizeram isso**. 48 | - Nós não tentamos convencer as pessoas a mudar, apenas ajudar as pessoas que já decidiram isso. 49 | - ⚠️ Esta é uma nova cheatsheet, toda ajuda é bem-vinda. 50 | - **Cheatsheet de HOCs** ([`/HOC.md`](https://react-typescript-cheatsheet.netlify.app/docs/hoc)) especificamente ensina as pessoas a escrever HOCs com a ajuda de exemplos. 51 | - Familiaridade com [Genéricos](https://www.typescriptlang.org/docs/handbook/generics.html) é necessário. 52 | - ⚠️ Esta é uma nova cheatsheet, toda a assistência é bem-vinda. 53 | 54 | --- 55 | 56 | ### Tabela de conteúdos da Cheatsheet básica 57 | 58 |
59 | 60 | Expandir Tabela de Conteúdo 61 | 62 | 63 | 64 | - [Seção 1: Configuração](#seção-1-configuração) 65 | - [Pré-requisitos](#pré-requisitos) 66 | - [Ferramentas iniciais de React + TypeScript](#ferramentas-iniciais-de-react--typeScript) 67 | - [Importar React](#importar-react) 68 | 69 | - [Seção 2: Primeiros Passos](#seção-2-primeiros-passos) 70 | - [Componente de Função](#componente-de-função) 71 | - [Hooks](#hooks) 72 | - [useState](#usestate) 73 | - [useReducer](#usereducer) 74 | - [useEffect](#useeffect) 75 | - [useRef](#useref) 76 | - [useImperativeHandle](#useimperativehandle) 77 | - [Hooks Customizados](#custom-hooks) 78 | - [Componentes de Classe](#class-components) 79 | - [Talvez você não precise do `defaultProps`](#you-may-not-need-defaultprops) 80 | - ["Tipando" `defaultProps`](#typing-defaultprops) 81 | - [Consumindo Props de um Componente com defaultProps](#consuming-props-of-a-component-with-defaultprops) 82 | - [Declaração do Problema](#problem-statement) 83 | - [Solução](#solution) 84 | - [Discussões e Conhecimentos Diversos](#misc-discussions-and-knowledge) 85 | - [Tipos ou Interfaces?](#types-or-interfaces) 86 | - [Exemplos básicos do tipo Prop](#basic-prop-types-examples) 87 | - [Exemplos úteis do tipo React Prop](#useful-react-prop-type-examples) 88 | - [getDerivedStateFromProps](#getDerivedStateFromProps) 89 | - [Formulários e Eventos](#forms-and-events) 90 | - [Context](#context) 91 | - [Exemplo Básico](#basic-example) 92 | - [Exemplo Extendido](#extended-example) 93 | - [forwardRef/createRef](#forwardrefcreateref) 94 | - [Portais](#portals) 95 | - [Limites de erros](#error-boundaries) 96 | - [Opção 1: Usando react-error-boundary](#option-1-using-react-error-boundary) 97 | - [Opção 2: Criando um componente "error boundary" personalizado](#options-2-writing-your-custom-error-boundary-component) 98 | - [Concurrent React/React Suspense](#concurrent-reactreact-suspense) 99 | 100 | - [Manual de resolução de problemas: Tipos](#troubleshooting-handbook-types) 101 | - [Tipos de União e Tipos de Proteção](#union-types-and-type-guarding) 102 | - [Tipos Opcionais](#optional-types) 103 | - [Tipos de Enum](#enum-types) 104 | - [Tipos de Asserção](#type-assertion) 105 | - [Simulando Tipos Nominais](#simulating-nominal-types) 106 | - [Tipos de Interseção](#intersection-types) 107 | - [Tipos de União](#union-types) 108 | - [Sobrecarregando Tipos de Função](#overloading-function-types) 109 | - [Usando Tipos Inferidos](#using-inferred-types) 110 | - [Usando Tipos Parciais](#using-partial-types) 111 | - [Os Tipos de que preciso não foram exportados!](#the-types-i-need-werent-exported) 112 | - [Os Tipos de que preciso não existem!](#the-types-i-need-dont-exist) 113 | - [Exagerando com `any` em tudo](#slapping-any-on-everything) 114 | - [Autogerando tipos](#autogenerate-types) 115 | - [Tipando Hooks Exportados](#typing-exported-hooks) 116 | - [Tipando Componentes Exportados](#typing-exported-components) 117 | 118 | - [Manual de resolução de problemas: Operadores](#troubleshooting-handbook-operators) 119 | - [Manual de resolução de problemas: Utilitários](#troubleshooting-handbook-utilities) 120 | - [Manual de resolução de problemas: tsconfig.json](#troubleshooting-handbook-tsconfigjson) 121 | - [Manual de resolução de problemas: Erros en tipos oficiais](#troubleshooting-handbook-bugs-in-official-typings) 122 | - [Bases de código de React + TypeScript recomendadas para aprender](#recommended-react--typescript-codebases-to-learn-from) 123 | - [Ferramentas e integração em editores](#editor-tooling-and-integration) 124 | - [Linting](#linting) 125 | - [Outros recursos sobre React + TypeScript](#other-react--typescript-resources) 126 | - [Discussões recomendadas sobre React + TypeScript](#recommended-react--typescript-talks) 127 | - [Hora de realmente aprender TypeScript](#time-to-really-learn-typescript) 128 | - [Aplicação de Exemplo](#example-app) 129 | - [Minha pergunta não foi respondida aqui!](#my-question-isnt-answered-here) 130 | - [Contribuidores](#contributors) 131 | 132 |
133 | 134 | 135 | 136 | # Seção 1: Configuração 137 | 138 | ## Pré-requisitos 139 | 140 | 1. Uma boa compreensão de [React](https://reactjs.org). 141 | 2. Familiaridade com os tipos básicos de [TypeScript](https://www.typescriptlang.org/docs/handbook/basic-types.html) ( [O guia de 2ality](http://2ality.com/2018/04/type-notation-typescript.html) é de grande ajuda. Se você é completamente novato em TypeScript, dê uma olhada no [tutorial de chibicode](https://ts.chibicode.com/todo/) ). 142 | 3. Ter lido [a seção de TypeScript na documentação oficial do React](https://reactjs.org/docs/static-type-checking.html#typescript). 143 | 4. Ter lido [a seção do React do novo playground de TypeScript](http://www.typescriptlang.org/play/index.html?jsx=2&esModuleInterop=true&e=181#example/typescript-with-react) ( Opcional: também acompanhar os mais de 40 exemplos na seção de exemplos do [playground](http://www.typescriptlang.org/play/index.html) ). 144 | 145 | Este guia sempre assumirá que você está usando a última versão de Typescript. Notas para versões mais antigas usarão a etiqueta `
`. 146 | 147 | ## Ferramentas iniciais de React + TypeScript 148 | 149 | Configurações na nuvem: 150 | 151 | - [Playground do TypeScript com React](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwCwAUKJLHAN5wCuqWAyjMhhYANFx4BRAgSz44AXzhES5Snhi1GjLAA8W8XBAB2qeAGEInQ0KjjtycABsscALxwAFAEpXAPnaM4OANjeABtA0sYUR4Yc0iAXVcxPgEhdwAGT3oGAOTJaXx3L19-BkDAgBMIXE4QLCsAOhhgGCckgAMATQsgh2BcAGssCrgAEjYIqwVmutR27MC5LM0yuEoYTihDD1zAgB4K4AA3H13yvbAfbs5e-qGRiYspuBmsVD2Aekuz-YAjThgMCMcCMpj6gxcbGKLj8MTiVnck3gAGo4ABGTxyU6rcrlMF3OB1H5wT7-QFGbG4z6HE65ZYMOSMIA) apenas se você estiver depurando tipos (e relatando problemas), não para executar código. 152 | - [CodeSandbox](http://ts.react.new) - IDE na nuvem, inicializa super rápido. 153 | - [Stackblitz](https://stackblitz.com/edit/react-typescript-base) - IDE na nuvem, inicializa super rápido. 154 | 155 | Configurações de desenvolvimento local: 156 | 157 | - [Next.js](https://nextjs.org/docs/basic-features/typescript): `npx create-next-app -e with-typescript` irá criar no seu diretório atual. 158 | - [Create React App](https://facebook.github.io/create-react-app/docs/adding-typescript): `npx create-react-app name-of-app --template typescript` irá criar em um novo diretório. 159 | - [Meteor](https://guide.meteor.com/build-tool.html#typescript): `meteor create --typescript name-of-my-new-typescript-app` 160 | - [Ignite](https://github.com/infinitered/ignite#use-ignite-andross-infinite-red-andross-boilerplate) para React Native: `ignite new myapp` 161 | - [TSDX](https://tsdx.io/): `npx tsdx create mylib` para Creating React+TS _libraries_ 162 | 163 |
164 | 165 | Outras ferramentas 166 | 167 | 168 | Ferramentas menos maduras mas que vale a pena conferir: 169 | 170 | - [Vite](https://twitter.com/swyx/status/1282727239230996480?lang=en): `npm init vite-app my-react-project --template react-ts` (nota - ainda não está na versão v1.0, mas é muito rápida). 171 | - [Snowpack](): `npx create-snowpack-app my-app --template app-template-react-typescript` 172 | - [Docusaurus v2](https://v2.docusaurus.io/docs/installation) com [suporte a TypeScript](https://v2.docusaurus.io/docs/typescript-support) 173 | - [Parcel](https://v2.parceljs.org/languages/typescript/) 174 | - [JP Morgan's `modular`](https://github.com/jpmorganchase/modular): CRA + TS + Yarn Workspaces toolkit. `yarn create modular-react-app ` 175 | 176 | Manual de configuração: 177 | 178 | - [O guia de Basarat](https://github.com/basarat/typescript-react/tree/master/01%20bootstrap) para uma **configuração manual** de React + TypeScript + Webpack + Babel. 179 | - Em particular, certifique-se de ter instalado `@types/react` e `@types/react-dom` .( [Leia mais sobre o projeto DefinitelyTyped caso você não esteja familiarizado](https://definitelytyped.org/) ). 180 | - Existem também muitos _boilerplates_ de React + Typescript. Por favor consulte [nossa lista de outros recursos](https://react-typescript-cheatsheet.netlify.app/docs/basic/recommended/resources/). 181 | 182 |
183 | 184 | ## Import React 185 | 186 | ```tsx 187 | import * as React from 'react'; 188 | import * as ReactDOM from 'react-dom'; 189 | ``` 190 | 191 | Este é o [caminho mais seguro no futuro](https://www.reddit.com/r/reactjs/comments/iyehol/import_react_from_react_will_go_away_in_distant/) para importar React. Se você definir `--allowSyntheticDefaultImports` (ou adicionar` "allowSyntheticDefaultImports": true`) em seu `tsconfig.json`, você poderá importar como se faz normalmente em jsx: 192 | 193 | ```tsx 194 | import React from 'react'; 195 | import ReactDOM from 'react-dom'; 196 | ``` 197 | 198 |
199 | 200 | Explicação 201 | 202 | Por que usar `allowSyntheticDefaultImports` ao invés de `esModuleInterop`? [Daniel Rosenwasser](https://twitter.com/drosenwasser/status/1003097042653073408) comentou que é melhor para webpack/parcel. Para consultar mais argumentos dessa discussão 203 | 204 | Você também deveria verificar [a nova documentação do TypeScript para descrições oficiais entre cada _flag_ do compilador](https://www.typescriptlang.org/tsconfig#allowSyntheticDefaultImports)! 205 | 206 |
207 | 208 | 209 | 210 | 211 | 212 | # Seção 2: Primeiros Passos 213 | 214 | ## Componente de Função 215 | 216 | Podem ser escritos como funções normais que recebem `props` como argumento e retornam um elemento JSX. 217 | 218 | ```tsx 219 | type AppProps = { message: string }; /* também se pode usar uma interface */ 220 | const App = ({ message }: AppProps) =>
{message}
; 221 | ``` 222 | 223 |
224 | 225 | Por que `React.FC` é desencorajado? E sobre `React.FunctionComponent` / `React.VoidFunctionComponent`? 226 | 227 | Você pode ver isso em muitas bases de código React + TypeScript: 228 | 229 | ```tsx 230 | const App: React.FunctionComponent<{ message: string }> = ({ message }) => ( 231 |
{message}
232 | ); 233 | ``` 234 | 235 | No entanto, o consenso geral hoje é que o uso de `React.FunctionComponent` (ou a abreviação` React.FC`) é [desencorajado] (https://github.com/facebook/create-react-app/pull/8177). Isto é um ponto de vista, é claro, mas se você concorda e deseja remover `React.FC` da sua base de código, você pode usar [este jscodeshift codemod] (https://github.com/gndelia/codemod-replace-react- fc-typescript). 236 | 237 | Algumas diferenças da versão de "função normal": 238 | 239 | - `React.FunctionComponent` é explícito sobre o tipo de retorno, enquanto a versão normal da função é implícita (ou então precisa de anotações adicionais). 240 | 241 | - Fornece verificação de tipos e preenchimento automático para propriedades estáticas como `displayName`,` propTypes` e `defaultProps`. 242 | 243 | - Observe que existem alguns problemas conhecidos usando `defaultProps` com` React.FunctionComponent`. Consulte [este problema para obter detalhes] (https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/87). Nós mantemos uma seção `defaultProps` separada para que você também possa consultar. 244 | 245 | - Fornece uma definição implícita de `children` (veja abaixo) - no entanto, há alguns problemas com o tipo `children` implícito (por exemplo, DefinitelyTyped#33006), e é melhor ser explícito sobre os componentes que consomem `children`, de qualquer maneira. 246 | 247 | ```tsx 248 | const Title: React.FunctionComponent<{ title: string }> = ({ 249 | children, 250 | title, 251 | }) =>
{children}
; 252 | ``` 253 | 254 |
255 | 256 | Usando `React.VoidFunctionComponent` ou` React.VFC` como alternativa 257 | 258 | 259 | A partir da versão [@types/react 16.9.48] (https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46643), você também poderá usar o tipo `React.VoidFunctionComponent` ou `React.VFC` se quiser tipar `children` explicitamente. Esta é uma solução provisória até que `FunctionComponent` não aceite nenhum `children` por padrão (planejado para `@types/react@^18.0.0`). 260 | 261 | ```ts 262 | type Props = { foo: string }; 263 | 264 | // OK agora mas futuramente causará erro 265 | const FunctionComponent: React.FunctionComponent = ({ 266 | foo, 267 | children, 268 | }: Props) => { 269 | return ( 270 |
271 | {foo} {children} 272 |
273 | ); // OK 274 | }; 275 | 276 | // OK agora mas futuramente se tornará obsoleto 277 | const VoidFunctionComponent: React.VoidFunctionComponent = ({ 278 | foo, 279 | children, 280 | }) => { 281 | return ( 282 |
283 | {foo} 284 | {children} 285 |
286 | ); 287 | }; 288 | ``` 289 | 290 |
291 | - _No futuro_, ele poderá marcar automaticamente os `props` como `readonly` (somente leitura), embora isso seja um ponto discutível se o objeto `props` for desestruturado na lista de parâmetros. 292 | 293 | Na maioria dos casos, faz pouca diferença qual sintaxe é usada, mas você pode preferir a natureza mais explícita de `React.FunctionComponent`. 294 | 295 |
296 | 297 |
298 | Problemas menores 299 | 300 | Esses padrões não são suportados: 301 | 302 | ** Renderização condicional ** 303 | 304 | ```tsx 305 | const MyConditionalComponent = ({ shouldRender = false }) => 306 | shouldRender ?
: false; // tampouco faça isso em JS 307 | const el = ; // gera um erro 308 | ``` 309 | 310 | Isso ocorre porque, devido às limitações do compilador, os componentes de função não podem retornar nada além de uma expressão JSX ou `null`, caso contrário, ele reclama com uma mensagem de erro enigmática dizendo que outro tipo não pode ser atribuído ao Elemento. 311 | 312 | ```tsx 313 | const MyArrayComponent = () => Array(5).fill(
); 314 | const el2 = ; // gera um erro 315 | ``` 316 | 317 | **Array.fill** 318 | 319 | Infelizmente, apenas anotar o tipo de função não vai ajudar, então se você realmente precisar retornar outros tipos exóticos que o React suporta, será necessário executar uma declaração de tipo: 320 | 321 | ```tsx 322 | const MyArrayComponent = () => (Array(5).fill(
) as any) as JSX.Element; 323 | ``` 324 | 325 | [Veja o comentário de @ferdaber aqui] (https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/57). 326 | 327 |
328 | 329 | 330 | 331 | 332 | 333 | ## Hooks 334 | 335 | Há suporte para Hooks em [`@types/react` a partir da versão v16.8](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L800-L1031). 336 | 337 | ## useState 338 | 339 | Inferência automática de tipos funciona bem com valores simples 340 | 341 | ```tsx 342 | const [val, toggle] = React.useState(false); 343 | // infere-se que `val` é do tipo boolean 344 | // `toggle` aceita apenas booleans 345 | ``` 346 | 347 | Veja também no artigo em inglês (utilizando [Using Inferred Types](https://react-typescript-cheatsheet.netlify.app/docs/basic/troubleshooting/types/#using-inferred-types) se precisar usar um tipo complexo para o qual você depende da inferência. 348 | 349 | No entanto, muitos hooks são inicializados com valores nulos e você pode se perguntar como deve fazer para definir o tipo. Declare explicitamente o tipo e use um tipo de união (union type): 350 | 351 | ```tsx 352 | const [user, setUser] = React.useState(null); 353 | 354 | // mais adiante... 355 | setUser(newUser); 356 | ``` 357 | 358 | Você também pode usar asserções de tipo (type assertions) se um estado for inicializado logo após o setup e sempre tiver um valor definido após o setup: 359 | 360 | ```tsx 361 | const [user, setUser] = React.useState({} as IUser); 362 | 363 | // mais adiante... 364 | setUser(newUser); 365 | ``` 366 | 367 | "Mentimos" temporariamente para o compilador de Typescript que `{}` é do tipo `IUser`. Você deve então configurar o estado de `user` — se não o fizer, o resto do seu código pode depender do fato de que `user` é do tipo `IUser` e isso pode levar a erros em tempo de execução (runtime errors). 368 | 369 | ## useReducer 370 | 371 | Você pode utilizar Uniões de tipos com propriedades definidas ([Discriminated Unions](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions)) para actions da função reducer. Não esqueça de definir o tipo de retorno, caso contário, o compilador irá inferir o tipo. 372 | 373 | ```tsx 374 | const initialState = { count: 0 }; 375 | 376 | type ACTIONTYPE = 377 | | { type: "increment"; payload: number } 378 | | { type: "decrement"; payload: string }; 379 | 380 | function reducer(state: typeof initialState, action: ACTIONTYPE) { 381 | switch (action.type) { 382 | case "increment": 383 | return { count: state.count + action.payload }; 384 | case "decrement": 385 | return { count: state.count - Number(action.payload) }; 386 | default: 387 | throw new Error(); 388 | } 389 | } 390 | 391 | function Counter() { 392 | const [state, dispatch] = React.useReducer(reducer, initialState); 393 | return ( 394 | <> 395 | Count: {state.count} 396 | 399 | 402 | 403 | ); 404 | } 405 | ``` 406 | 407 | [Veja no TypeScript Playground](https://www.typescriptlang.org/play?#code/LAKFEsFsAcHsCcAuACAVMghgZ2QJQKYYDGKAZvLJMgOTyEnUDcooRsAdliuO+IuBgA2AZUQZE+ZAF5kAbzYBXdogBcyAAwBfZmBCIAntEkBBAMIAVAJIB5AHLmAmgAUAotOShkyAD5zkBozVqHiI6SHxlagAaZGgMfUFYDAATNXYFSAAjfHhNDxAvX1l-Q3wg5PxQ-HDImLiEpNTkLngeAHM8ll1SJRJwDmQ6ZIUiHIAKLnEykqNYUmQePgERMQkY4n4ONTMrO0dXAEo5T2aAdz4iAAtkMY3+9gA6APwj2ROvImxJYPYqmsRqCp3l5BvhEAp4Ow5IplGpJhIHjCUABqTB9DgPeqJFLaYGfLDfCp-CIAoEFEFeOjgyHQ2BKVTNVb4RF05TIAC0yFsGWy8Fu6MeWMaB1x5K8FVIGAUglUwK8iEuFFOyHY+GVLngFD5Bx0Xk0oH13V6myhplZEm1x3JbE4KAA2vD8DFkuAsHFEFcALruAgbB4KAkEYajPlDEY5GKLfhCURTHUnKkQqFjYEAHgAfHLkGb6WpZI6WfTDRSvKnMgpEIgBhxTIJwEQANZSWRjI5SdPIF1u8RXMayZ7lSphEnRWLxbFNagAVmomhF6fZqYA9OXKxxM2KQWWK1WoTW643m63pB2u+7e-3SkEQsPamOGik1FO55p08jl6vdxuKcvv8h4yAmhAA) 408 | 409 |
410 | 411 | Uso do tipo `Reducer` da biblioteca `redux` 412 | 413 | Caso você use a biblioteca [redux](https://github.com/reduxjs/redux) para escrever a reducer function, ela fornece um helper conveniente do formato `Reducer` que cuida do tipo do retorno para você. 414 | 415 | Assim, o exemplo de reducer acima se torna: 416 | 417 | ```tsx 418 | import { Reducer } from 'redux'; 419 | 420 | export function reducer: Reducer() {} 421 | ``` 422 | 423 |
424 | 425 | ## useEffect / useLayoutEffect 426 | 427 | Ambos `useEffect` e `useLayoutEffect` são usados para executar efeitos colaterais e retornam uma função de limpeza opcional, o que significa que se eles não lidam com retorno de valores, nenhum tipo é necessário. Ao usar `useEffect`, tome cuidado para não retornar nada além de uma função ou `undefined`, caso contrário, tanto o TypeScript quanto o React apresentarão error. Isso pode ser sutil ao usar arrow functions: 428 | 429 | ```ts 430 | function DelayedEffect(props: { timerMs: number }) { 431 | const { timerMs } = props; 432 | 433 | useEffect( 434 | () => 435 | setTimeout(() => { 436 | /* faça coisas aqui */ 437 | }, timerMs), 438 | [timerMs] 439 | ); 440 | // um exemplo ruim! setTimeout implicitamente retorna número (tipo number) 441 | // porque o corpo da arrow function não está entre chaves 442 | return null; 443 | } 444 | ``` 445 | 446 |
447 | 448 | Solução para o exemplo acima 449 | 450 | 451 | ```tsx 452 | function DelayedEffect(props: { timerMs: number }) { 453 | const { timerMs } = props; 454 | 455 | useEffect(() => { 456 | setTimeout(() => { 457 | /* faça coisas aqui */ 458 | }, timerMs); 459 | }, [timerMs]); 460 | // melhor; utilize a keyword void para ter certeza de que retornará undefined 461 | return null; 462 | } 463 | ``` 464 | 465 |
466 | 467 | ## useRef 468 | 469 | Em TypeScript, `useRef` retorna uma referência que pode ser [somente leitura](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/abd69803c1b710db58d511f4544ec1b70bc9077c/types/react/v16/index.d.ts#L1025-L1039) ou [mutável](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/abd69803c1b710db58d511f4544ec1b70bc9077c/types/react/v16/index.d.ts#L1012-L1023), a depender se o tipo fornecido cobre totalmente o valor inicial ou não. Escolha um que se adapte ao seu caso de uso. 470 | 471 | ### Opção 1: ref de um elemento da DOM 472 | 473 | **[Para acessar um elemento da DOM](https://reactjs.org/docs/refs-and-the-dom.html):** forneça apenas o tipo de elemento como argumento e use `null` como valor inicial. Neste caso, a referência retornada terá um `.current` somente leitura que é gerenciado pelo React. O TypeScript espera que você dê esta referência à prop `ref` de um elemento: 474 | 475 | ```tsx 476 | function Foo() { 477 | // - Se possível, seja o mais específico possível. Por exemplo, HTMLDivElement 478 | // é melhor que HTMLElement e muito melhor que Element. 479 | // - Em termos técnicos, isso retorna RefObject 480 | const divRef = useRef(null); 481 | 482 | useEffect(() => { 483 | // Observe que ref.current pode ser null. Isso é esperado, porque você pode 484 | // renderizar condicionalmente o elemento da ref, ou você poderia esquecer de atribuí-lo a um elemento 485 | if (!divRef.current) throw Error("divRef is not assigned"); 486 | 487 | // Agora você tem certeza que divRef.current é um HTMLDivElement 488 | doSomethingWith(divRef.current); 489 | }); 490 | 491 | // Atribua a ref a um elemento para que o React possa gerenciar-lo pra você 492 | return
etc
; 493 | } 494 | ``` 495 | 496 | Se você tem certeza de que `divRef.current` nunca será nulo, também é possível usar o operador de asserção não nulo `!`: 497 | 498 | ```tsx 499 | const divRef = useRef(null!); 500 | // Mais tarde... não precisa checar se o elemento é nulo 501 | doSomethingWith(divRef.current); 502 | ``` 503 | 504 | Observe que você está desativando a segurança de tipo aqui - você terá um erro de tempo de execução se esquecer de atribuir a referência a um elemento na renderização ou se o elemento com ref for renderizado condicionalmente. 505 | 506 |
507 | 508 | Dica: Escolhendo qual `HTMLElement` usar 509 | 510 | 511 | Refs demandam especificidade - não é suficiente apenas especificar qualquer `HTMLElement` antigo. Se você não souber o nome do tipo de elemento necessário, verifique [lib.dom.ts](https://github.com/microsoft/TypeScript/blob/v3.9.5/lib/lib.dom. d.ts#L19224-L19343) ou cometa um erro de tipo intencional e deixe o compilador lhe dizer o tipo correto: 512 | 513 | ![image](https://user-images.githubusercontent.com/6764957/116914284-1c436380-ac7d-11eb-9150-f52c571c5f07.png) 514 | 515 |
516 | 517 | ### Opção 2: Valor ref mutável 518 | 519 | **[Para ter um valor mutável](https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables):** forneça o tipo desejado e verifique se o valor inicial pertence totalmente a esse tipo: 520 | 521 | ```tsx 522 | function Foo() { 523 | // Tecnicamente, isto retorna MutableRefObject 524 | const intervalRef = useRef(null); 525 | 526 | // Você mesmo gerência a ref (por isso se chama MutableRefObject!) 527 | useEffect(() => { 528 | intervalRef.current = setInterval(...); 529 | return () => clearInterval(intervalRef.current); 530 | }, []); 531 | 532 | // A ref (intervalRef) não é passado para a prop "ref" de nenhum elemento 533 | return ; 534 | } 535 | ``` 536 | 537 | ### Veja também (conteúdo em inglês) 538 | 539 | - [Issue relacionada por @rajivpunjabi](https://github.com/typescript-cheatsheets/react/issues/388) - [Playground](https://www.typescriptlang.org/play#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcARFDvmQNwCwAUI7hAHarwCCYYcAvHAAUASn4A+OAG9GjOHAD0CBLLnKGcxHABiwKBzgQwMYGxS4WUACbBWAczgwIcSxFwBXEFlYxkxtgDoVTQBJVmBjZAAbOAA3KLcsOAB3YEjogCNE1jc0-zgAGQBPG3tHOAAVQrAsAGVcKGAjOHTCuDdUErhWNgBabLSUVFQsWBNWA2qoX2hA9VU4AGFKXyx0AFk3H3TIxOwCOAB5dIArLHwgpHcoSm84MGJJmFbgdG74ZcsDVkjC2Y01f7yFQsdjvLAEACM-EwVBg-naWD2AB4ABLlNb5GpgZCsACiO083jEgn6kQAhMJ6HMQfpKJCFpE2IkBNg8HCEci0RisTj8VhCTBiaSKVSVIoAaoLnBQuFgFFYvFEikBpkujkMps4FgAB7VfCdLmY7F4gleOFwAByEHg7U63VYfXVg2Go1MhhG0ygf3mAHVUtF6jgYLtwUdTvguta4Bstjs9mGznCpVcbvB7u7YM90B8vj9vYgLkDqWxaeCAEzQ1n4eHDTnoo2801EknqykyObii5SmpnNifA5GMZmCzWOwOJwudwC3xjKUyiLROKRBLJf3NLJO9KanV64xj0koVifQ08k38s1Sv0DJZBxIx5DbRGhk6J5Nua5mu4PEZPOAvSNgsgnxsHmXZzIgRZyDSYIEAAzJWsI1k+BCovWp58gKcAAD5qmkQqtqKHbyCexoYRecw7IQugcAs76ptCdIQv4KZmoRcjyMRaGkU28A4aSKiUXAwwgpYtEfrcAh0mWzF0ax7bsZx3Lceetx8eqAlYPAMAABa6KJskSXAdKwTJ4kwGxCjyKy-bfK05SrDA8mWVagHAbZeScOY0CjqUE6uOgqDaRAOSfKqOYgb8KiMaZ9GSeCEIMkyMVyUwRHWYc7nSvAgUQEk6AjMQXpReWyWGdFLHeBZHEuTCQEZT8xVwaV8BxZCzUWZQMDvuMghBHASJVnCWhTLYApiH1chIqgxpGeCfCSIxAC+Yj3o+8YvvgSLyNNOLjeBGhTTNdLzVJy3reGMBbTtrB7RoB3XbNBAneCsHLatcbPhdV3GrdB1WYhw3IKNZq-W2DCLYRO7QPAljgsgORcDwVJAA) 540 | - [Exemplo de Stefan Baumgartner](https://fettblog.eu/typescript-react/hooks/#useref) - [Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgIilQ3wFgAoCzAVwDsNgJa4AVJADxgElaxqYA6sBgALAGIQ01AM4AhfjCYAKAJRwA3hThwA9DrjBaw4CgA2waUjgB3YSLi1qp0wBo4AI35wYSZ6wCeYEgAymhQwGDw1lYoRHCmEBAA1oYA5nCY0HAozAASLACyADI8fDAAoqZIIEi0MFpwaEzS8IZllXAAvIjEMAB0MkjImAA8+cWl-JXVtTAAfEqOzioA3A1NtC1wTPIwirQAwuZoSV1wql1zGg3aenAt4RgOTqaNIkgn0g5ISAAmcDJvBA3h9TsBMAZeFNXjl-lIoEQ6nAOBZ+jddPpPPAmGgrPDEfAUS1pG5hAYvhAITBAlZxiUoRUqjU6m5RIDhOi7iIUF9RFYaqIIP9MlJpABCOCAUHJ0eDzm1oXAAGSKyHtUx9fGzNSacjaPWq6Ea6gI2Z9EUyVRrXV6gC+DRtVu0RBgxuYSnRIzm6O06h0ACpIdlfr9jExSQyOkxTP5GjkPFZBv9bKIDYSmbNpH04ABNFD+CV+nR2636kby+BETCddTlyo27w0zr4HycfC6L0lvUjLH7baHY5Jas7BRMI7AE42uYSUXed6pkY6HtMDulnQruCrCg2oA) 541 | 542 | ## useImperativeHandle 543 | 544 | _Não temos muito ainda sobre esse tema, [há uma discussão nas issues do repositório original](https://github.com/typescript-cheatsheets/react/issues/106). Por favor, contribua se puder!_ 545 | 546 | ```tsx 547 | type ListProps = { 548 | items: ItemType[]; 549 | innerRef?: React.Ref<{ scrollToItem(item: ItemType): void }>; 550 | }; 551 | 552 | function List(props: ListProps) { 553 | useImperativeHandle(props.innerRef, () => ({ 554 | scrollToItem() {}, 555 | })); 556 | return null; 557 | } 558 | ``` 559 | 560 | ## Custom Hooks 561 | 562 | Se você estiver retornando um array em seu Custom Hook (hooks customizados), você vai querer evitar a inferência de tipo, pois o TypeScript irá inferir um tipo de união (quando, na verdade, você quer tipos diferentes em cada posição do array). Em vez disso, use [const assertions do TypeScript 3.4](https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#const-assertions): 563 | 564 | ```tsx 565 | export function useLoading() { 566 | const [isLoading, setState] = React.useState(false); 567 | const load = (aPromise: Promise) => { 568 | setState(true); 569 | return aPromise.finally(() => setState(false)); 570 | }; 571 | return [isLoading, load] as const; // infere [boolean, typeof load] ao invés de (boolean | typeof load)[] 572 | } 573 | ``` 574 | 575 | [Veja no TypeScript Playground](https://www.typescriptlang.org/play/?target=5&jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoCpAD0ljkwFcA7DYCZuRgZyQBkIKACbBmAcwAUASjgBvCnDhoO3eAG1g3AcNFiANHF4wAyjBQwkAXTgBeRMRgA6HklPmkEzCgA2vKQG4FJRV4b0EhWzgJFAAFHBBNJAAuODjcRIAeFGYATwA+GRs8uSDFIzcLCRgoRiQA0rgiGEYoTlj4xMdMUR9vHIlpW2Lys0qvXzr68kUAX0DpxqRm1rgNLXDdAzDhaxRuYOZVfzgAehO4UUwkKH21ACMICG9UZgMYHLAkCEw4baFrUSqVARb5RB5PF5wAA+cHen1BfykaksFBmQA) 576 | 577 | Dessa forma, quando você desestrutura (desctructure), você obtém os tipos certos com base na posição de desestruturação. 578 | 579 | 580 | Alternativa: definir um tipo de retorno de tupla (tuple) 581 | 582 | Se você está [tendo problemas com const assertions](https://github.com/babel/babel/issues/9800), você também pode declarar ou definir os tipos do retorno da função: 583 | 584 | ```tsx 585 | export function useLoading() { 586 | const [isLoading, setState] = React.useState(false); 587 | const load = (aPromise: Promise) => { 588 | setState(true); 589 | return aPromise.finally(() => setState(false)); 590 | }; 591 | return [isLoading, load] as [ 592 | boolean, 593 | (aPromise: Promise) => Promise 594 | ]; 595 | } 596 | ``` 597 | 598 | Uma função auxiliar que define o tipe de tuplas automaticamente também pode ser útil se você escrever muitos custom hooks: 599 | 600 | ```tsx 601 | function tuplify(...elements: T) { 602 | return elements; 603 | } 604 | 605 | function useArray() { 606 | const numberValue = useRef(3).current; 607 | const functionValue = useRef(() => {}).current; 608 | return [numberValue, functionValue]; // o tipo fica (number | (() => void))[] 609 | } 610 | 611 | function useTuple() { 612 | const numberValue = useRef(3).current; 613 | const functionValue = useRef(() => {}).current; 614 | return tuplify(numberValue, functionValue); // o tipo fica [number, () => void] 615 | } 616 | ``` 617 | 618 |
619 | 620 | Saiba que a equipe do React recomenda que custom hooks que retornam mais de dois valores usem objetos em vez de tuplas. 621 | 622 | ## Leituras sobre Hooks + TypeScript (em inglês): 623 | 624 | - https://medium.com/@jrwebdev/react-hooks-in-typescript-88fce7001d0d 625 | - https://fettblog.eu/typescript-react/hooks/#useref 626 | 627 | Se você estiver escrevendo uma biblioteca de Hooks, não esqueça que você também deve expor os tipos para os usuários utilizarem. 628 | 629 | ## Exemploes de bibliotecas React Hooks + TypeScript: 630 | 631 | - https://github.com/mweststrate/use-st8 632 | - https://github.com/palmerhq/the-platform 633 | - https://github.com/sw-yx/hooks 634 | 635 | [Tem algo a acrescentar? - link para o repositório original](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/new). 636 | 637 | --------------------------------------------------------------------------------