写在前面 要想在react + typescript 项目中正确的使用 hooks ,请务必掌握泛型的使用,关于泛型的讲解,我在上一篇博文中详细的进行了介绍,如果你还不了解 typescript 中的泛型请看上一篇:正确认识typescript中的泛型 。
如何结合typescript正确使用hooks 在react中使用函数式组件,难免会使用到hooks,hooks赋予了函数式组件可以像 class 组件那样拥有状态的能力,那么如何结合typescript正确的使用hooks呢?
在react + typescript项目中正确使用useState 如果想编写一个 Header 组件,使其具备一个登录和退出的功能,登录的时候,显示一些提示已经登录的文字,退出的时候显示欢迎的文字,那么我们很容易知道:如果使用函数式组件来编写此 Header 组件,那么就一定会用到 useState ,因为登录与否的状态是该组件自身的状态,所以就会用到hooks中的 useState 来赋予函数式组件状态。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import React, { useState } from 'react' export default function Header ( ) { const [isLogin, setIsLogin] = useState(false ); const _logout = () => { setIsLogin(false ) } const _login = () => { setIsLogin(true ) } return ( <div > {isLogin ? <p > You have logined in!</p > : <p > welcome, guest!</p > } {isLogin ? <button onClick ={_logout} > 退出</button > : <button onClick ={_login} > 登录</button > } </div > ) }
其实在第五行const [isLogin, setIsLogin] = useState(false);
使用useState赋予初始值false的时候,后续在调用setIsLogin
函数时,ts 编译器就会自动推断你传入的参数是不是boolean类型的,若不是,则会报错。第五行,我们也可以进行显式的进行限制,传入泛型,就像这样const [isLogin, setIsLogin] = useState<boolean>(false);
我们也可以把要显示的文案也抽象成为组件的一个状态,这样我们就不需要再写三元表达式了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import React, { useState } from 'react' export default function Header ( ) { const [isLogin, setIsLogin] = useState<boolean>(false ); const [text, setText] = useState<string>('' ); const _logout = () => { setIsLogin(false ); setText('welcome, guest!' ); } const _login = () => { setIsLogin(true ); setText('You have logined in!' ); } return ( <div > <p > { text }</p > {isLogin ? <button onClick ={_logout} > 退出</button > : <button onClick ={_login} > 登录</button > } </div > ) }
这里的函数setIsLogin
只能传入布尔类型的值,函数setText
只能传入 string 类型的值,传别的类型都会报错。 这里的两个状态比较简单,一个是布尔类型,一个是 string 类型,可能体现不出typescript的强大之处,那么我们再增加一个状态用户信息:const [user, setUser] = useState<UserType | null>(null)
,完整代码如下:
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 import React, { useState } from 'react' type UserType = { name : string; age: number; addr: string; } export default function Header ( ) { const [isLogin, setIsLogin] = useState<boolean>(false ); const [text, setText] = useState<string>('' ); const [user, setUser] = useState<UserType | null >(null ) const _logout = () => { setIsLogin(false ); setText('welcome, guest!' ); setUser(null ) } const _login = () => { setIsLogin(true ); setText('You have logined in!' ); setUser({ name : '小明' , age : 18 , addr : '深圳市南山区深圳湾河里' }) } return ( <div > <p > { text }</p > <p > username is {user?.name}, user's age is {user?.age}, user's address is {user?.addr}</p > {isLogin ? <button onClick ={_logout} > 退出</button > : <button onClick ={_login} > 登录</button > } </div > ) }
我们给useState显式的传入泛型UserType或者null,就表示我们在后续调用setUser的时候,就只能传入UserType 类型的值或者 null 类型的值,否则ts编译器就会告诉你传值错误。这样做,我们在开发过程中可以省去了很多麻烦,可维护性也更好。
代码地址及文件路径 注: 本文代码github仓库地址:ts中正确使用useState 文件路径:src/components/Header.tsx
。