react+ts
react.FC
type FC<P = {}> = FunctionComponent<P>type PropsWithChildren<P> = P & { children?: ReactNode }interface FunctionComponent<P = {}> {(props: PropsWithChildren<P>, context?: any): ReactElement<any,any> | nullpropTypes?: WeakValidationMap<P>contextTypes?: ValidationMap<any>defaultProps?: Partial<P>displayName?: string}
Create-react-app 从模板中删除 React.FC
https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/function_components
使用 FC 需要注意:
- 组件 defaultProps 使用 es6 方式
- 无法使用泛型
- 返回类型是 ReactElement 和 null(不包含 undefined,string 等)
尽量不要指定组件的 return 类型(ReactNode 或者 JSX.Element),而是让 ts 自己去推断。
类型会自动推断
初始值是 null 使用联合类型 useState<P | null>(null)
useRef\<HTMLElement>(null!) or useRef\<HTMLElement | null>(null)
尽量不用
!
(Non-null、Non-undefined),而是使用非 null 后者非 undefined 代码块。程序更易读自定义 hooks 注意返回值的类型推断
export function useLoading() {const [isLoading, setState] = React.useState(false)const load = (aPromise: Promise<any>) => {setState(true)return aPromise.finally(() => setState(false))}return [isLoading, load] as const // infers [boolean, typeof load] instead of (boolean | typeof load)[]}When declaring a mutable variable or property, TypeScript often widens values to make sure that we can assign things later on without writing an explicit type.
在声明可变变量或属性时,TypeScript 通常会加宽值,以确保以后可以分配内容而无需编写显式类型
使用 const 断言,将 literal types 、object literals、array literals 变成 readonly
- 函数式组件尽量使用 es6 默认赋值
能使用 interface 就是用 interface,库中 interface 方便重载
具体区别请看《重拾 ts》中两个对比
prop types
对象
不使用 object 和{},详细指定具体的属性
函数
指定入参和返回值
事件函数 指定具体的事件类型,使用泛型指定具体的元素
//用法1 作为方法handleClick(event: React.MouseEvent<HTMLButtonElement>) {event.preventDefault();alert(event.currentTarget.tagName); // alerts BUTTON}//用法2 作为props传递 可参考DefinitelyTyped/types/react/index.d.ts DOMAttributesinterface Props {handleClick:React.MouseEventHandler<HTMLButtonElement>//orhandleClick: (event:React.MouseEvent<HTMLButtonElement>)=>void}AnimationEvent
,ChangeEvent
,ClipboardEvent
,CompositionEvent
,DragEvent
,FocusEvent
,FormEvent
,KeyboardEvent
,MouseEvent
,PointerEvent
,TouchEvent
,TransitionEvent
,WheelEvent
. As well asSyntheticEvent
JSX.Element
orJSX.Element[]
React.ReactChildren
orReact.ReactChild[]
orReact.ReactNode
React.CSSProperties
指定 style 对象
注意:请查看《重拾 ts》JSX.Element 和 React.ReactNode 的对比
JSX.Element
vsReact.ReactNode
vsReact.ReactElement
JSX.Element
-> Return value ofReact.createElement
React.ReactNode
-> Return value of a component
declare namespce React {interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {type: T;props: P;key: Key | null;}type ReactText = string | number;type ReactChild = ReactElement | ReactText;interface ReactNodeArray extends Array<ReactNode> {}type ReactFragment = {} | ReactNodeArray;type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;}declare global {namespace JSX {interface Element extends React.ReactElement<any, any> { }}}从上面可以看出,ReactElement 和 JSX.Element 基本类似。ReactNode 类型更多
什么时候使用 JSX.Element vs ReactNode vs ReactElement?
forwardRef/createRef
class 组件中 createRef 必须指定具体的元素。
class CssThemeProvider extends React.PureComponent<Props> {private rootRef = React.createRef<HTMLDivElement>() // like thisrender() {return <div ref={this.rootRef}>{this.props.children}</div>}}forwardRef