-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathWhen and why would I want to use SFC declaration.md
115 lines (88 loc) · 2.67 KB
/
When and why would I want to use SFC declaration.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# When and why would I want to use SFC declaration
## Ok way
Normally, when defining a react component in typescript, we only specify the `props` and leave the typescript to figure out the component/function type. E.g.
```typescript
// interface.ts
import { ReactNode, CSSProperties } from 'react';
export interface IContainerProps {
children: ReactNode;
style?: CSSProperties;
}
```
```typescript
// container.tsx - only define props
import React from 'react';
import { IContainerProps } from './interface.ts'
export default function Container(props: IContainerProps) {
const { children, style = {}} = props;
return (
<div style={style ? style : {}}>
{children}
</div>
);
}
```
`Container` would then be inferred with the type `function Container(props: IContainerProps): JSX.Element`
### ReactElement
```typescript
interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
type: T;
props: P;
key: Key | null;
}
```
`<div> abc </div>` is a ReactElement as it is indeed equivalent to:
```javascript
{
$$typeof: Symbol(react.element),
props: { children: 'abc' },
type: 'div',
...
}
```
### ReactNode
```typescript
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
type ReactChild = ReactElement | ReactText;
type ReactText = string | number
type ReactFragment = {} | ReactNodeArray
interface ReactNodeArray extends Array<ReactNode> {}
```
## Better way
Notice that we have to define `children` prop in `IContainerProps`, we can optimize this with `SFC`
```typescript
import React, { SFC } from 'react';
import { IContainerProps } from './interface';
const Container: SFC<IContainerProps> = (props) => {
const { children, style = {} } = props;
return (
<div style={style ? style : {}}>
{children}
</div>
);
}
export default Container;
```
```typescript
import { CSSProperties } from 'react';
export interface IContainerProps {
style?: CSSProperties;
}
```
It works as `SFC` (which is basically `FunctionComponent`) has defined the `children` with generic type.
```typescript
type SFC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
```
```typescript
type PropsWithChildren<P> = P & { children?: ReactNode };
```
Note here `type` can be used to generate a new `type definition`
## Notice
* If you want to follow the latest news/articles for the series of my blogs, Please [「Watch」](https://github.com/n0ruSh/blogs/)to Subscribe.