还算完整的React+TS类型,阿里P7亲自教你

本文详细介绍了ReactHooks(useState,useRef,useEffect,useCallback,useMemo)如何支持泛型以及类型推导,展示了如何在自定义Hook和组件Props中使用类型声明,包括默认参数、interface与type的区别,以及如何通过查找类型来优化组件属性类型。
摘要由CSDN通过智能技术生成

useState自动推导,或者传入泛型

useRef自动推导,或者传入泛型,如(<HTMLInputElement | null>)

useEffect固定,返回值只能是undefined和()=>{}

useMemouseCallback 自动推导返回值 从它们返回的值中推断出它们的类型 也可传入泛型多此一举

useCallback 参数必须指定类型,否则ts不会报错,默认指定为 any

使用推导类型作为接口/类型:

const [user] = React.useState({ name: ‘sj’, age: 32 })//自动推导出类型

const showUser = React.useCallback((obj: typeof user) => {//这里typeof使用推导出的类型✅

return My name is ${obj.name}, My age is ${obj.age}

}, [])

初始状态为null时候,需要显示声明类型:

type User = {name:string}

const [user, setUser] = React.useState<User | null>(null)

useRef的类型:

const ref1 = React.useRef(null)//ref1.current 是只读的

const ref2 = React.useRef<HTMLInputElement | null>(null)//ref2.current 是可变的✅

//可是这样声明貌似不能使用ref来保存setTimeout❌

const ref1 = React.useRef(null)//暂时这样吧

//一个场景focus

const onButtonClick = () => {

ref2.current?.focus()//可以使用可选链

}

//其他

// 存储div dom

const divRef = React.useRef<HTMLDivElement | null>(null);

// 存储button dom

const buttonRef = React.useRef<HTMLButtonElement | null>(null);

// 存储a dom

const linkRef = React.useRef<HTMLLinkElement | null>(null);

useMemo和useCallback:

// 自动推断 (value: number) => number

const multiply = React.useCallback((value: number) => value * multiplier, [

multiplier,

])

//泛型

//同时也支持传入泛型, useMemo 的泛型指定了返回值类型,useCallback 的泛型指定了参数类型

const handleChange = React.useCallback<

React.ChangeEventHandler

(evt => {

console.log(evt.target.value)

}, [])

自定义Hooks:

//自定义 Hook 的返回值如果是数组类型,TS 会自动推导为 Union 类型,解决:const断言

function useLoading() {

const [isLoading, setState] = React.useState(false)

const load = (aPromise: Promise) => {

setState(true)

return aPromise.then(() => setState(false))

}

// 实际需要: [boolean, typeof load] 类型

// 而不是自动推导的:(boolean | typeof load)[]

return [isLoading, load] as const //这个hook把isLoading和一个函数返回出去✅

}

//大量的自定义 Hook 需要处理,这里有一个方便的工具方法可以处理 tuple 返回值

function tuplify<T extends any[]>(…elements: T) {

return elements

}

//[boolean, typeof load]

把上面例子 return [isLoading, load] as const 改为=> return tuplify(isLoading, load)

defaultProps


推荐方式:使用默认参数值来代替默认属性

看了字节的那个例子,…有点麻烦,还要交叉类型,表示再也不会用defaultProps了

注意的是有这样一个类型React.ComponentProps

const TestComponent = (props: React.ComponentProps) => {

return

}

Types or Interfaces


巧用type:

let user = { name: ‘Lucy’, age: 20 }

type User = typeof user;✅//user{name:string,age:number}

选择:

  1. 在定义公共 API 时(比如编辑一个库)使用 interface,这样可以方便使用者继承接口

  2. 在定义组件属性(Props)和状态(State)时,建议使用 type,因为 type的约束性更强

区别:

  1. type 类型不能二次编辑,而 interface 可以随时扩展

type Animal = {

name: string

}

// type类型不支持属性扩展

// Error: Duplicate identifier ‘Animal’

type Animal = {

color: string

}

//但interface能

  1. type 可以定义更多类型,interface只能定义对象

注释:

/**

  • @param color color

*/

Props


常用:

type AppProps = {

status: ‘waiting’ | ‘success’//字面量加联合类型

obj: {//列出对象的全部属性,这里也可以写个interface

id: string

title: string

}

/** array of objects! (common) */

objArr: {✅//曾几何时,一度不知道这样写== 数组里面多个对象

id: string

title: string

}[]

/** 携带点击事件的函数 */

onClick(event: React.MouseEvent): void

//可选

onClick?: () => void

}

React属性:

export declare interface AppBetterProps {

children: React.ReactNode // 一般情况下推荐使用,支持所有类型 Great

functionChildren: (name: string) => React.ReactNode

style?: React.CSSProperties // 传递style对象

onChange?: React.FormEventHandler

}

export declare interface AppProps {

children1: JSX.Element // 差, 不支持数组

children2: JSX.Element | JSX.Element[] // 一般, 不支持字符串

children3: React.ReactChildren // 忽略命名,不是一个合适的类型,工具类类型

children4: React.ReactChild[] // 很好

children: React.ReactNode // 最佳,支持所有类型 推荐使用

functionChildren: (name: string) => React.ReactNode // recommended function as a child render prop type

style?: React.CSSProperties // 传递style对象

onChange?: React.FormEventHandler // 表单事件, 泛型参数是event.target的类型

}

Forms and Events


onChange:

import * as React from ‘react’

//第一种·

type changeFn = (e: React.FormEvent) => void//这样定义下面onchange的参数和返回值

const App: React.FC = () => {

const [state, setState] = React.useState(‘’)

const onChange: changeFn = e => {

setState(e.currentTarget.value)

}

//第二种,强制使用 @types / react 提供的委托类型

const onChange: React.ChangeEventHandler = e => {✅

setState(e.currentTarget.value)

}

return (

)

}

onSubmit:

const onSubmit = (e: React.SyntheticEvent) => {✅

e.preventDefault()

const target = e.target as typeof e.target & {

password: { value: string }

} // 类型扩展—表示看不懂—

const password = target.password.value

}

Operators(运算符)


常用的操作符,常用于类型判断 ---- 只会用常用的 = =

  • typeof and instanceof: 用于类型区分

  • keyof: 获取object的key

  • O[K]: 属性查找

  • + or - or readonly or ?: 加法、减法、只读和可选修饰符

  • x ? Y : Z: 用于泛型类型、类型别名、函数参数类型的条件类型

  • !: 可空类型的空断言

  • as: 类型断言

  • is: 函数返回类型的类型保护

Tips


😥使用查找类型访问组件属性类型

这个场景我理解是:子组件必须接受一个name参数,父组件要把它的props传入子组件,那么父组件要拿到子组件这个必要的类型来定义自己的Iprops

总的来说就是React.ComponentProps<typeof Counter>拿到子组件必要类型,再用交叉类型&,定义自己的Iprops

通过查找类型减少 type 的非必要导出,如果需要提供复杂的 type,应当提取到作为公共 API 导出的文件中。

现在我们有一个 Counter 组件,需要 name 这个必传参数:

// counter.tsx

import * as React from ‘react’

export type Props = {//app要用,所以export😎

name: string

}

const Counter: React.FC = props => {

return <></>

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

这里分享一份由字节前端面试官整理的「2021大厂前端面试手册」,内容囊括Html、CSS、Javascript、Vue、HTTP、浏览器面试题、数据结构与算法。全部整理在下方文档中,共计111道

HTML

  • HTML5有哪些新特性?

  • Doctype作⽤? 严格模式与混杂模式如何区分?它们有何意义?

  • 如何实现浏览器内多个标签页之间的通信?

  • ⾏内元素有哪些?块级元素有哪些? 空(void)元素有那些?⾏内元 素和块级元素有什么区别?

  • 简述⼀下src与href的区别?

  • cookies,sessionStorage,localStorage 的区别?

  • HTML5 的离线储存的使用和原理?

  • 怎样处理 移动端 1px 被 渲染成 2px 问题?

  • iframe 的优缺点?

  • Canvas 和 SVG 图形的区别是什么?

JavaScript

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 问:0.1 + 0.2 === 0.3 嘛?为什么?

  • JS 数据类型

  • 写代码:实现函数能够深度克隆基本类型

  • 事件流

  • 事件是如何实现的?

  • new 一个函数发生了什么

  • 什么是作用域?

  • JS 隐式转换,显示转换

  • 了解 this 嘛,bind,call,apply 具体指什么

  • 手写 bind、apply、call

  • setTimeout(fn, 0)多久才执行,Event Loop

  • 手写题:Promise 原理

  • 说一下原型链和原型链的继承吧

  • 数组能够调用的函数有那些?

  • PWA使用过吗?serviceWorker的使用原理是啥?

  • ES6 之前使用 prototype 实现继承

  • 箭头函数和普通函数有啥区别?箭头函数能当构造函数吗?

  • 事件循环机制 (Event Loop)


ps://img-blog.csdnimg.cn/img_convert/476288e164f5711c5c11e55a79185bd8.png)

JavaScript

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 问:0.1 + 0.2 === 0.3 嘛?为什么?

  • JS 数据类型

  • 写代码:实现函数能够深度克隆基本类型

  • 事件流

  • 事件是如何实现的?

  • new 一个函数发生了什么

  • 什么是作用域?

  • JS 隐式转换,显示转换

  • 了解 this 嘛,bind,call,apply 具体指什么

  • 手写 bind、apply、call

  • setTimeout(fn, 0)多久才执行,Event Loop

  • 手写题:Promise 原理

  • 说一下原型链和原型链的继承吧

  • 数组能够调用的函数有那些?

  • PWA使用过吗?serviceWorker的使用原理是啥?

  • ES6 之前使用 prototype 实现继承

  • 箭头函数和普通函数有啥区别?箭头函数能当构造函数吗?

  • 事件循环机制 (Event Loop)

  • 24
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值