Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

yarn pretty-quick --staged
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"trailingComma": "es5"
}
29 changes: 14 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ Some differences from the "normal function" version:
- `React.FunctionComponent` is explicit about the return type, while the normal function version is implicit (or else needs additional annotation).

- It provides typechecking and autocomplete for static properties like `displayName`, `propTypes`, and `defaultProps`.

- Note that there are some known issues using `defaultProps` with `React.FunctionComponent`. See [this issue for details](https://github.com/typescript-cheatsheets/react/issues/87). We maintain a separate `defaultProps` section you can also look up.

- Before the [React 18 type updates](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210), `React.FunctionComponent` provided an implicit definition of `children` (see below), which was heavily debated and is one of the reasons [`React.FC` was removed from the Create React App TypeScript template](https://github.com/facebook/create-react-app/pull/8177).
Expand Down Expand Up @@ -362,7 +361,7 @@ In React >= 18, the function signature of `useCallback` changed to the following
function useCallback<T extends Function>(callback: T, deps: DependencyList): T;
```

Therefore, the following code will yield "`Parameter 'e' implicitly has an 'any' type.`" error in React >= 18, but not <17.
Therefore, the following code will yield "`Parameter 'e' implicitly has an 'any' type.`" error in React >= 18, but not &lt;17.

```ts
// @ts-expect-error Parameter 'e' implicitly has 'any' type.
Expand Down Expand Up @@ -646,7 +645,7 @@ export function useLoading() {
};
return [isLoading, load] as [
boolean,
(aPromise: Promise<any>) => Promise<any>
(aPromise: Promise<any>) => Promise<any>,
];
}
```
Expand Down Expand Up @@ -825,7 +824,7 @@ class Comp extends React.Component<Props, State> {
```tsx
class Comp extends React.Component<
Props,
ReturnType<typeof Comp["getDerivedStateFromProps"]>
ReturnType<(typeof Comp)["getDerivedStateFromProps"]>
> {
static getDerivedStateFromProps(props: Props) {}
}
Expand Down Expand Up @@ -1295,7 +1294,7 @@ class Comp extends React.Component<Props, State> {
```tsx
class Comp extends React.Component<
Props,
ReturnType<typeof Comp["getDerivedStateFromProps"]>
ReturnType<(typeof Comp)["getDerivedStateFromProps"]>
> {
static getDerivedStateFromProps(props: Props) {}
}
Expand Down Expand Up @@ -1383,10 +1382,10 @@ class App extends React.Component<Props, State> {
Instead of typing the arguments and return values with `React.FormEvent<>` and `void`, you may alternatively apply types to the event handler itself (_contributed by @TomasHubelbauer_):

```tsx
// typing on LEFT hand side of =
onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
this.setState({text: e.currentTarget.value})
}
// typing on LEFT hand side of =
onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
this.setState({ text: e.currentTarget.value });
};
```

<details>
Expand Down Expand Up @@ -1814,9 +1813,9 @@ If you need both generic support and proper forwardRef behavior with full type i
```tsx
// Add to your type definitions (e.g. in `index.d.ts` file)
interface ForwardRefWithGenerics extends React.FC<WithForwardRefProps<Option>> {
<T extends Option>(props: WithForwardRefProps<T>): ReturnType<
React.FC<WithForwardRefProps<T>>
>;
<T extends Option>(
props: WithForwardRefProps<T>
): ReturnType<React.FC<WithForwardRefProps<T>>>;
}

export const ClickableListWithForwardRef: ForwardRefWithGenerics =
Expand Down Expand Up @@ -2015,7 +2014,7 @@ export default ErrorBoundary;

#### Concurrent React/React Suspense

_Not written yet._ watch <https://github.com/sw-yx/fresh-async-react> for more on React Suspense and Time Slicing.
_Not written yet._ watch [https://github.com/sw-yx/fresh-async-react](https://github.com/sw-yx/fresh-async-react) for more on React Suspense and Time Slicing.

[Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).

Expand Down Expand Up @@ -2929,9 +2928,9 @@ If you're looking for information on Prettier, check out the [Prettier](https://

### Other React + TypeScript resources

- me! <https://twitter.com/swyx>
- me! [https://twitter.com/swyx](https://twitter.com/swyx)
- https://www.freecodecamp.org/news/how-to-build-a-todo-app-with-react-typescript-nodejs-and-mongodb/
- <https://github.com/piotrwitek/react-redux-typescript-guide> - **HIGHLY HIGHLY RECOMMENDED**, i wrote this repo before knowing about this one, this has a lot of stuff I don't cover, including **REDUX** and **JEST**.
- [https://github.com/piotrwitek/react-redux-typescript-guide](https://github.com/piotrwitek/react-redux-typescript-guide) - **HIGHLY HIGHLY RECOMMENDED**, i wrote this repo before knowing about this one, this has a lot of stuff I don't cover, including **REDUX** and **JEST**.
- [10 Bad TypeScript Habits](https://startup-cto.net/10-bad-typescript-habits-to-break-this-year/):
1. not using `"strict": true`
2. using `||` for default values when we have `??`
Expand Down
8 changes: 4 additions & 4 deletions docs/advanced/misc-concerns.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default Object.assign(Form, { Input: Input });

I do like [Docz](https://docz.site/) which takes basically [1 line of config](https://www.docz.site/documentation/project-configuration#typescript) to accept TypeScript. However it is newer and has a few more rough edges (many breaking changes since it is still < v1.0)

For developing with Storybook, read the docs I wrote over here: <https://storybook.js.org/configurations/typescript-config/>. This includes automatic proptype documentation generation, which is awesome :)
For developing with Storybook, read the docs I wrote over here: [https://storybook.js.org/configurations/typescript-config/](https://storybook.js.org/configurations/typescript-config/). This includes automatic proptype documentation generation, which is awesome :)

[Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).

Expand All @@ -99,9 +99,9 @@ You should check out large projects that are migrating from flow to pick up conc

Useful libraries:

- <https://github.com/bcherny/flow-to-typescript>
- <https://github.com/Khan/flow-to-ts>
- <https://github.com/piotrwitek/utility-types>
- [https://github.com/bcherny/flow-to-typescript](https://github.com/bcherny/flow-to-typescript)
- [https://github.com/Khan/flow-to-ts](https://github.com/Khan/flow-to-ts)
- [https://github.com/piotrwitek/utility-types](https://github.com/piotrwitek/utility-types)

If you have specific advice in this area, please file a PR!

Expand Down
16 changes: 8 additions & 8 deletions docs/advanced/patterns_by_usecase.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ Example:

```tsx
// ReactUtilityTypes.d.ts
declare type $ElementProps<T> = T extends React.ComponentType<infer Props>
? Props extends object
? Props
: never
: never;
declare type $ElementProps<T> =
T extends React.ComponentType<infer Props>
? Props extends object
? Props
: never
: never;
```

Usage:
Expand All @@ -142,7 +143,7 @@ Usage:
import * as Recompose from "recompose";
export const defaultProps = <
C extends React.ComponentType,
D extends Partial<$ElementProps<C>>
D extends Partial<$ElementProps<C>>,
>(
defaults: D,
Component: C
Expand Down Expand Up @@ -635,8 +636,7 @@ function App() {
}
```

<a href="https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwBQdMAnmFnAArFjoC8dccAD5wA3vwETgqAIJQoyJgC44MKAFcs9CRIBuyADYblqVcAB2AcwDaAXRpxxAgL7jhY7QKmz5SuAQOomo66BkZwJlDmFloSTvS4EGYmcAAacDxwABRgypwQ3ACU6QB8ouKUMGpQZphUMAB0aoEAslggEJnBmUU8pZ0ecAA8ACbAOsXB2nqGWJmoBYqTEiJg9V5yCnAAZFtwq9Ma9QBWEOaZZAA0ZAUuAwIiAISr6z7bu-uhWLcegwD0o+NggULsErM8ZBsmBc9vUDlgbNDfr84AAVFhYVC4SJgeDINQwEjIGDAXAGfRMOAgIm4AAWGJUdLgCTkGMgZlGljgcJU6PEBXocToBDUZnwwEScGkYDA3TKAgqVRq-QkIzGTP0aFQADlkCAsDwAERSsAGiYDQZpF4KHgifz6QJOLmfG1kAgQCBkR2-M0-S0Qnw21QaR1wm1WV3uy7kABGyCgUbIsYAXmQbF6fQI-gCffy6E4gA"><i>See this in TS Playground</i>
</a>
[_See this in TS Playground_](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwBQdMAnmFnAArFjoC8dccAD5wA3vwETgqAIJQoyJgC44MKAFcs9CRIBuyADYblqVcAB2AcwDaAXRpxxAgL7jhY7QKmz5SuAQOomo66BkZwJlDmFloSTvS4EGYmcAAacDxwABRgypwQ3ACU6QB8ouKUMGpQZphUMAB0aoEAslggEJnBmUU8pZ0ecAA8ACbAOsXB2nqGWJmoBYqTEiJg9V5yCnAAZFtwq9Ma9QBWEOaZZAA0ZAUuAwIiAISr6z7bu-uhWLcegwD0o+NggULsErM8ZBsmBc9vUDlgbNDfr84AAVFhYVC4SJgeDINQwEjIGDAXAGfRMOAgIm4AAWGJUdLgCTkGMgZlGljgcJU6PEBXocToBDUZnwwEScGkYDA3TKAgqVRq-QkIzGTP0aFQADlkCAsDwAERSsAGiYDQZpF4KHgifz6QJOLmfG1kAgQCBkR2-M0-S0Qnw21QaR1wm1WV3uy7kABGyCgUbIsYAXmQbF6fQI-gCffy6E4gA)

In the above example, based on the `isArray` union member, the type of the `value` hook dependency changes.

Expand Down
1 change: 0 additions & 1 deletion docs/advanced/patterns_by_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,6 @@ You can [convert these in bulk](https://github.com/microsoft/TypeScript/pull/374
[[Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) | [Blog Post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/)]

- [Variadic Tuple Types](https://devblogs.microsoft.com/typescript/announcing-typescript-4-0-beta/#variadic-tuple-types)

- useful for [simplified Reducer-like State](https://www.reddit.com/r/reactjs/comments/hu0ytg/simplified_reducerlike_state_using_typescript_40/)

- [Custom JSX Factories](https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/#custom-jsx-factories)
Expand Down
2 changes: 1 addition & 1 deletion docs/basic/getting-started/class-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class Comp extends React.Component<Props, State> {
```tsx
class Comp extends React.Component<
Props,
ReturnType<typeof Comp["getDerivedStateFromProps"]>
ReturnType<(typeof Comp)["getDerivedStateFromProps"]>
> {
static getDerivedStateFromProps(props: Props) {}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/basic/getting-started/concurrent.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ id: concurrent
title: Concurrent React/React Suspense
---

_Not written yet._ watch <https://github.com/sw-yx/fresh-async-react> for more on React Suspense and Time Slicing.
_Not written yet._ watch [https://github.com/sw-yx/fresh-async-react](https://github.com/sw-yx/fresh-async-react) for more on React Suspense and Time Slicing.

[Something to add? File an issue](https://github.com/typescript-cheatsheets/react/issues/new).
8 changes: 4 additions & 4 deletions docs/basic/getting-started/forms-and-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ class App extends React.Component<Props, State> {
Instead of typing the arguments and return values with `React.FormEvent<>` and `void`, you may alternatively apply types to the event handler itself (_contributed by @TomasHubelbauer_):

```tsx
// typing on LEFT hand side of =
onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
this.setState({text: e.currentTarget.value})
}
// typing on LEFT hand side of =
onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
this.setState({ text: e.currentTarget.value });
};
```

<details>
Expand Down
6 changes: 3 additions & 3 deletions docs/basic/getting-started/forward-create-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,9 @@ If you need both generic support and proper forwardRef behavior with full type i
```tsx
// Add to your type definitions (e.g. in `index.d.ts` file)
interface ForwardRefWithGenerics extends React.FC<WithForwardRefProps<Option>> {
<T extends Option>(props: WithForwardRefProps<T>): ReturnType<
React.FC<WithForwardRefProps<T>>
>;
<T extends Option>(
props: WithForwardRefProps<T>
): ReturnType<React.FC<WithForwardRefProps<T>>>;
}

export const ClickableListWithForwardRef: ForwardRefWithGenerics =
Expand Down
1 change: 0 additions & 1 deletion docs/basic/getting-started/function-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ Some differences from the "normal function" version:
- `React.FunctionComponent` is explicit about the return type, while the normal function version is implicit (or else needs additional annotation).

- It provides typechecking and autocomplete for static properties like `displayName`, `propTypes`, and `defaultProps`.

- Note that there are some known issues using `defaultProps` with `React.FunctionComponent`. See [this issue for details](https://github.com/typescript-cheatsheets/react/issues/87). We maintain a separate `defaultProps` section you can also look up.

- Before the [React 18 type updates](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210), `React.FunctionComponent` provided an implicit definition of `children` (see below), which was heavily debated and is one of the reasons [`React.FC` was removed from the Create React App TypeScript template](https://github.com/facebook/create-react-app/pull/8177).
Expand Down
4 changes: 2 additions & 2 deletions docs/basic/getting-started/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ In React >= 18, the function signature of `useCallback` changed to the following
function useCallback<T extends Function>(callback: T, deps: DependencyList): T;
```

Therefore, the following code will yield "`Parameter 'e' implicitly has an 'any' type.`" error in React >= 18, but not <17.
Therefore, the following code will yield "`Parameter 'e' implicitly has an 'any' type.`" error in React >= 18, but not &lt;17.

```ts
// @ts-expect-error Parameter 'e' implicitly has 'any' type.
Expand Down Expand Up @@ -355,7 +355,7 @@ export function useLoading() {
};
return [isLoading, load] as [
boolean,
(aPromise: Promise<any>) => Promise<any>
(aPromise: Promise<any>) => Promise<any>,
];
}
```
Expand Down
4 changes: 2 additions & 2 deletions docs/basic/recommended/codebases.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ React Boilerplates:
- https://github.com/rwieruch/nextjs-firebase-authentication: Next.js + Firebase Starter: styled, tested, typed, and authenticated
- [@jpavon/react-scripts-ts](https://github.com/jpavon/react-scripts-ts) alternative react-scripts with all TypeScript features using [ts-loader](https://github.com/TypeStrong/ts-loader)
- [webpack config tool](https://webpack.jakoblind.no/) is a visual tool for creating webpack projects with React and TypeScript
- <https://github.com/innFactory/create-react-app-material-typescript-redux> ready to go template with [Material-UI](https://material-ui.com/), routing and Redux
- [https://github.com/innFactory/create-react-app-material-typescript-redux](https://github.com/innFactory/create-react-app-material-typescript-redux) ready to go template with [Material-UI](https://material-ui.com/), routing and Redux

React Native Boilerplates: _contributed by [@spoeck](https://github.com/typescript-cheatsheets/react/pull/20)_

- https://github.com/GeekyAnts/react-native-seed
- https://github.com/lopezjurip/ReactNativeTS
- https://github.com/emin93/react-native-template-typescript
- <https://github.com/Microsoft/TypeScript-React-Native-Starter>
- [https://github.com/Microsoft/TypeScript-React-Native-Starter](https://github.com/Microsoft/TypeScript-React-Native-Starter)

TS Library Codebases to study

Expand Down
4 changes: 2 additions & 2 deletions docs/basic/recommended/resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ title: Other React + TypeScript resources
sidebar_label: Other resources
---

- me! <https://twitter.com/swyx>
- me! [https://twitter.com/swyx](https://twitter.com/swyx)
- https://www.freecodecamp.org/news/how-to-build-a-todo-app-with-react-typescript-nodejs-and-mongodb/
- <https://github.com/piotrwitek/react-redux-typescript-guide> - **HIGHLY HIGHLY RECOMMENDED**, i wrote this repo before knowing about this one, this has a lot of stuff I don't cover, including **REDUX** and **JEST**.
- [https://github.com/piotrwitek/react-redux-typescript-guide](https://github.com/piotrwitek/react-redux-typescript-guide) - **HIGHLY HIGHLY RECOMMENDED**, i wrote this repo before knowing about this one, this has a lot of stuff I don't cover, including **REDUX** and **JEST**.
- [10 Bad TypeScript Habits](https://startup-cto.net/10-bad-typescript-habits-to-break-this-year/):
1. not using `"strict": true`
2. using `||` for default values when we have `??`
Expand Down
2 changes: 1 addition & 1 deletion docs/hoc/react-hoc-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ interface WithSubscriptionProps {
}

function withSubscription<
T extends WithSubscriptionProps = WithSubscriptionProps
T extends WithSubscriptionProps = WithSubscriptionProps,
>(WrappedComponent: React.ComponentType<T>) {
class WithSubscription extends React.Component {
/* ... */
Expand Down
19 changes: 10 additions & 9 deletions genReadme.js → genReadme.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const fs = require("fs/promises");
const path = require("path");
const Fm = require("front-matter");
const Toc = require("markdown-toc");
const prettier = require("prettier");
const yargs = require("yargs/yargs");
const { hideBin } = require("yargs/helpers");
import fs from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
import Fm from "front-matter";
import Toc from "markdown-toc";
import prettier from "prettier";
import yargs from "yargs/yargs";
import { hideBin } from "yargs/helpers";

const repositoryRootPath = __dirname;
const repositoryRootPath = path.dirname(fileURLToPath(import.meta.url));
const readmePath = path.resolve(repositoryRootPath, "./README.md");
/**
* level of the heading under which the generated content is displayed
Expand Down Expand Up @@ -336,7 +337,7 @@ async function main(argv) {
});

const prettierConfig = await prettier.resolveConfig(readmePath);
pendingReadme = prettier.format(pendingReadme, {
pendingReadme = await prettier.format(pendingReadme, {
...prettierConfig,
filepath: path.basename(readmePath),
});
Expand Down
3 changes: 3 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@

# Directory with the serverless Lambda functions to deploy to AWS.
# functions = "project/functions/"

[build.environment]
NODE_VERSION = "20"
15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,27 @@
"url": "https://github.com/typescript-cheatsheets/react/issues"
},
"homepage": "https://github.com/typescript-cheatsheets/react#readme",
"engines": {
"node": ">=20"
},
"scripts": {
"format-readme": "prettier --write \"README.md\"",
"gen-readme": "node genReadme.js",
"gen-readme": "node genReadme.mjs",
"format": "prettier --write \"**/*.md\"",
"format:check": "prettier --check \"**/*.md\"",
"postinstall": "cd website && yarn",
"prepare": "husky install",
"prepare": "husky",
"start": "yarn --cwd website start",
"build": "yarn --cwd website build"
},
"dependencies": {
"front-matter": "^4.0.2",
"markdown-toc": "^1.2.0",
"yargs": "^17.5.1"
"yargs": "^18.0.0"
},
"devDependencies": {
"husky": "^7.0.0",
"prettier": "^2.6.2",
"pretty-quick": "^3.1.3"
"husky": "^9.1.7",
"prettier": "^3.8.3",
"pretty-quick": "^4.2.2"
}
}
15 changes: 9 additions & 6 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
"swizzle": "docusaurus swizzle",
"deploy": "yarn add-pages-on-site && docusaurus deploy"
},
"engines": {
"node": ">=20"
},
"dependencies": {
"@docusaurus/core": "^2.4.0",
"@docusaurus/preset-classic": "^2.4.0",
"classnames": "^2.3.2",
"prism-react-renderer": "^2.4.0",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"@docusaurus/core": "^3.10.1",
"@docusaurus/preset-classic": "^3.10.1",
"classnames": "^2.5.1",
"prism-react-renderer": "^2.4.1",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"browserslist": {
"production": [
Expand Down
Loading
Loading