Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 25f3d5a

Browse filesBrowse files
committed
Initial translation 🎉
1 parent b526ede commit 25f3d5a
Copy full SHA for 25f3d5a

File tree

Expand file treeCollapse file tree

1 file changed

+208
-0
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+208
-0
lines changed

‎README.md

Copy file name to clipboardExpand all lines: README.md
+208Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,211 @@ const MyArrayComponent = () => (Array(5).fill(<div />) as any) as JSX.Element;
331331
<!--START-SECTION:hooks-->
332332

333333
## 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<IUser | null>(null);
353+
354+
// mais tarde...
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<IUser>({} as IUser);
362+
363+
// mais tarde...
364+
setUser(newUser);
365+
```
366+
367+
"Metimos" temporariamente para o compilador de Typesctipr 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+
<button onClick={() => dispatch({ type: "decrement", payload: "5" })}>
397+
-
398+
</button>
399+
<button onClick={() => dispatch({ type: "increment", payload: 5 })}>
400+
+
401+
</button>
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+
<details>
410+
411+
<summary><b>Uso do tipo `Reducer` da biblioteca `redux`</b></summary>
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<State, Action>` 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<AppState, Action>() {}
421+
```
422+
423+
</details>
424+
425+
## useEffect / useLayoutEffect
426+
427+
Ambos `useEffect` e `useLayoutEffect` são usados para executar <b>efeitos colaterais</b> e retornam uma função de limpeza opcional, o que significa que se eles não lidam com retorn 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+
<details>
447+
<summary>
448+
Solução para o exemplo acima
449+
</summary>
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+
</details>
466+
467+
## useRef
468+
469+
Em TypeScript, `useRef` retorn 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+
### Opção um 1: ref de um elemento da DOM
471+
472+
**[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:
473+
474+
```tsx
475+
function Foo() {
476+
// - Se possível, seja o mais específico possível. Por exemplo, HTMLDivElement
477+
// é melhor que HTMLElement e muito melhor que Element.
478+
// - Em termos técnicos, isso retorna RefObject<HTMLDivElement>
479+
const divRef = useRef<HTMLDivElement>(null);
480+
481+
useEffect(() => {
482+
// Observe que ref.current pode ser null. Isso é esperado, porque você pode
483+
// renderizar condicionalmente o elemento da ref, ou você poderia esquecer de atribuí-lo a um elemento
484+
if (!divRef.current) throw Error("divRef is not assigned");
485+
486+
// Agora você tem certeza que divRef.current é um HTMLDivElement
487+
doSomethingWith(divRef.current);
488+
});
489+
490+
// Atribua a ref a um elemento para que o React possa gerenciar-lo pra você
491+
return <div ref={divRef}>etc</div>;
492+
}
493+
```
494+
495+
Se você tem certeza de que `divRef.current` nunca será nulo, também é possível usar o operador de asserção não nulo `!`:
496+
497+
```
498+
const divRef = useRef<HTMLDivElement>(null!);
499+
// Mais tarde... não precisa checar se o elemento é nulo
500+
doSomethingWith(divRef.current);
501+
```
502+
503+
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.
504+
505+
<details>
506+
<summary>
507+
508+
Dica: Escolhendo qual `HTMLElement` usar
509+
510+
</summary>
511+
512+
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:
513+
514+
![image](https://user-images.githubusercontent.com/6764957/116914284-1c436380-ac7d-11eb-9150-f52c571c5f07.png)
515+
516+
</details>
517+
518+
### Opção 2: Valor ref mutável
519+
520+
**[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:
521+
522+
```tsx
523+
function Foo() {
524+
// Tecnicamente, isto retorna MutableRefObject<number | null>
525+
const intervalRef = useRef<number | null>(null);
526+
527+
// Você mesmo genrencia a ref (por isso se chama MutableRefObject!)
528+
useEffect(() => {
529+
intervalRef.current = setInterval(...);
530+
return () => clearInterval(intervalRef.current);
531+
}, []);
532+
533+
// A ref (intervalRef) não é passado para a prop "ref" de nenhum elemento
534+
return <button onClick={/* clearInterval the ref */}>Cancel timer</button>;
535+
}
536+
```
537+
538+
### Veja também (conteúdo em inglês)
539+
540+
- [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)
541+
- [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)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.