Part2-React+TS
一、项目创建与准备
1、创建项目
创建名为 hook-ts 的项目:
$ npx create-react-app hook-ts --template typescript
$ cd hook-ts
# 通过vscode打开
$ code .可以看到,整个项目的组件,都是使用tsx做后缀的,而普通的js文件,也使用的是ts作为后缀名。
注意:
1、在React中,以js为后缀名文件也可以作为组件使用,但在React+TS中,请慎用。最好区分开,ts代表js,tsx代表jsx。
2、js与jsx也可以在React+TS中使用,是兼容的,只是既然使用了ts,那就尽量使用ts和tsx代替它们。
2、项目初始化
先把 src 下所有的文件清空,并新建 index.ts 与 App.tsx 。
mac用户:
$ cd src
$ rm *
# 创建index.ts与App.tsx
$ touch index.ts App.tsx
# 返回根目录
$ cd ..win用户手动删或执行 del * 可删除src下的文件,或者打开 git bash 也可操作以上命令。
3、App组件
任意给 App.tsx 写点内容:
4、项目入口文件
在 index.ts 中:
但是你会发现一直报错:
原因是ts文件会被解析为js,而React+TS的项目是不允许ts成为一个组件的,因此只需要将 index.ts 改为 index.tsx 即可。
5、项目运行
最后,项目根目录下运行:
即可将项目运行。
二、Function Component
1、tsconfig
项目中如果每次都使用相对路径引入组件,就比较麻烦,这里推荐配置 tsconfig.json:
修改以上这几项,其中jsx的配置解释:
preserve
<div />
<div />
.jsx
react
<div />
React.createElement("div")
.js
你可以通过在命令行里使用--jsx标记或 tsconfig.json 里的选项来指定模式。
具体配置文档:https://www.tslang.cn/docs。
设置完成后重跑项目,此时引入组件的方式发生变更:
2、函数式组件
src 下新建 components ,再在其中创建 Comp1.tsx:
然后在 App.tsx 中引入:
其实不写React.FC也可以。React.FC表示:React.Function Component。React.FC 显式地定义了返回类型,其他方式是隐式推导的。
三、Hooks
函数式组件必备Hook,本教程结合TS一起讲解。
1、useState
App.tsx 中使用 useState 定义数据,以及修改数据的方法,并传递给 Comp.tsx 子组件:
子组件接收:
很明显,这么接收直接就报错。因为TS强制要求必须指定传参的字段及其类型,因此应当改为:
而实际上这是TS中接口的简化写法,完整点应该写为:
A. 事件直接父传子使用
目前 setNum 依然处于定义了但未使用的状态,因此ESlint又会一直给出提示,因此我们可以把这个累加的效果实现:
注意:
这里虽然设置为any可以实现累加,但不建议这么操作。
因此,真正的做法:
B. 事件用子传父的做法
* 父组件
setNum(newValue):代表直接用新值替换初始值
setNum(preValue => newValue):代表用新值替换旧值
* 子组件
2、useEffect
React的Class Component中有 componentDidMount、 componentDidUpdate 和 componentWillUnmount,但Function Component并没有。
A、componentDidMount
B、comopnentDidUpdate
如果监听路由的变化:
C、componentWillUnmount
3、memo、useMemo与useCallback
在Function Component中,也不再区分mount和update两个状态,这意味着函数组件的每一次调用都会执行内部的所有逻辑,就带来了非常大的性能损耗。useMemo和useCallback都是解决上述性能问题的。
来看下面这段代码:
以上代码中可以测试出来,Sub组件的 console.log 在App2组件更新时,一直被迫触发,这就是典型的性能浪费。
A. memo
使用memo这个hook可以解决这一问题:
memo可以缓存组件,当组件的内容不受修改时,可以不更新该组件。
B. useCallback
但我们希望num的变化不造成Sub组件的更新:
C. useMemo
useMemo与useCallback大致相同,只是useMemo需要在回调函数中再返回一个函数,我们称之为高阶函数:
4、自定义hook
React中的hook允许我们自定义,来尝试一个简单的:
自定义一个hook,将所有的小写字母改大写。
四、React Redux
需求:使用TS+React Redux实现一个累加。
A. 安装
B. Store
src下新建 store 目录,在其中新建 reducer.ts 和 index.ts:
a. reducer
b. store
C. Provider
在入口文件 index.tsx 中:
D. connect
在组件中:
五、路由
1、安装路由
本课程使用目前最新版的React路由(v6):
注意:
版本会随时更新,因此请指定版本安装。
2、路由配置
a. 路由创建
在 src 下创建 router>index.tsx。以首页与登录页切换为例:
关键词解析:
1、BrowserRouter重命名为Router
2、所有的Route组件必须放在Routes组件中
3、Route标签上的element属性必须填写标签结构的组件,如:,而不是 Home
4、加了index属性的路由不需要写path,因为/路径就指向该组件
b. 入口文件引入路由
src>index.tsx :
c. 组件显示
App.tsx 中:
关键词解析:
1、 组件用来显示子路由,类似于Vue的
2、Link最终会被html解析为a标签
目前结合ts的情况下,无法使用index属性指定首页组件,因此如果希望 / 跳转 /home,需要:
3、参数获取
a. 子路由形式携带
路由跳转往往伴随着参数的传递,假如:
此时可以使用React Router Dom提供的Hook来获取:
b. 问号(?)形式参数
获取形式:
以上的id其实属于携带方式不明确,也不一定会携带,因此路由可以设置为:
4、事件跳转
事件中执行跳转页面,可以使用useNavigate这个hook进行跳转。
简单参数的传递可以直接带在url后,而复杂参数需要以复杂数据类型的形式携带:
注意:
navigate方法第二个参数必须是对象,而且这个对象只接受replace和state两个属性,state可以用来携带参数。
携带复杂参数,可以使用useLocation来获取参数:
注意:
这里如果使用了TS,那么location会报错,因为其中的state属于不确定的类型,因此没办法直接location.state调用。解决方法有两个:一是单独设置state字段为any,二是直接设置location类型为any。
5、404匹配
当路由为404时,可以对路由文件 router/index.tsx 进行如下匹配:
如此,输入错误路径,就会自动重定向到404页面了。
最后更新于
这有帮助吗?
