本文适合会使用react以及了解ts语法的人
最近在学习react+ts在项目中的使用,走了几天弯路.说来奇怪,分开都能理解什么意思,可是react+ts一起用就不知道咋下手了.总结了一下这几天所理解的react+ts的使用,参考视频b站搬运视频
Getting started!
1.在组件中的使用
-
在类组件中的使用
首先类组件是没有hooks,在类组件中主要使用到的就是props,state和生命周期函数,ts在类组件中使用主要给props和state添加类型
组件内部
import React, {Component} from 'react' type MyProps = { type: string lang: string level: string } type MyState = { name: string } //给组件的props和state添加类型 export default class App extends Component<MyProps, MyState> { state = { name: 'zhangsan', } render() { return ( <div> <p>my name is {this.state.name}</p> <h1> 这是在{this.props.type}中使用{this.props.lang},难以程度: {this.props.level} </h1> </div> ) } } 使用组件
<App type="函数组件" lang="ts" level="easy" /> -
在函数组件中的使用
函数组件中主要在props和hooks中对ts进行使用,由于hooks比较复杂,单独在下面进行描述,此处只有关于ts在函数组件中props的使用
props
1.传值
2.传事件
3.传样式
4.传children
组件内部
import React from 'react' //props类型 type MyProps = { name: string age: number email: string style?: any onClick: (event: React.MouseEvent<HTMLButtonElement>) => void children: React.ReactNode } const StyleObj = {width: 400, backgroundColor: 'skyblue', padding: 40} export default function App(MyProps: MyProps) { let { //传样式 style, //传值并设置默认值 name = 'jony', age = 15, email = 'jony@163.com', //传事件 onClick, //传children children, } = MyProps //设置默认样式,传递进来不覆盖 style = Object.assign({ ...StyleObj, ...style, }) return ( <div style={{ backgroundColor: style.backgroundColor, width: style.width, paddingLeft: style.padding, }}> {children} <p> <i>name</i>:{name} </p> <p> <i>age</i>:{age} </p> <p> <i>email</i>:{email} </p> <button onClick={(e) => onClick(e)}>添加好友</button> </div> ) } 使用组件
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => { console.log('按钮点击', e) } <App name="彭于晏" age={42} email="yuyanpeng@qq.com" onClick={(e) => handleClick(e)} style={{backgroundColor: 'orange', width: 500}}> hahaha </App>5.传组件/组件作为props的属性传进来
首先涉及到三个组件
1.渲染组件的组件
引入两个组件 一个作为另一个的component
import React from 'react' import Box from './Box' import {Time} from './Time' export default function App() { return ( <div style={{backgroundColor: 'pink'}}> <h1>AppComponent</h1> <Box showTime={true} component={Time} /> </div> ) }2.props中有component组件
import React from 'react' import {TimePropsType} from './Time' type BoxPropsType = { showTime: boolean //如果component组件有props类型 要赋值过来 component: React.ComponentType<TimePropsType> } export default function Box({showTime, component: Component}: BoxPropsType) { if (showTime) { return <Component name="诸葛亮" /> } else { return ( <div style={{backgroundColor: 'skyblue'}}> <h1>BoxComponent</h1> </div> ) } } 3.作为component的组件
import React from 'react' export type TimePropsType = { name: string } export function Time(TimeProps: TimePropsType) { return ( <div> <h1>Time</h1> <h2>I'm {TimeProps.name},现在是2022年</h2> </div> ) }
2.在hooks中的使用
1.useState
当在使用useState给函数组件提供状态的时候,如果给了初始值 那么通过类型推断 就会推断出这个状态的类型,当赋值为其他类型的时候就会进行报错 如果future value 是其他类型怎么办呢 接下来就是ts在useState中的应用
当不设置类型时 ---->一直都是number
但是有时候 我们要获得的值是很复杂的,甚至有时候类型是不一样的 怎么解决呢?
此时 通过给useState设置类型即可解决
也可以使用类型断言
2.useRef
useRef可以用来获取dom 也可以来存储值 所以分两种情况
获取dom---在useRef后加dom类型
import React, {useEffect, useRef} from 'react'
export default function App() {
// 关于null!由于视频是英本的 本人英语能力有限 理解是非空 百度未查到
const buttonRef = useRef<HTMLButtonElement>(null!)
useEffect(() => {
console.log(buttonRef.current)
}, [])
return (
<div>
<h1>useRef-hooks</h1>
<h2>用来获取dom</h2>
<button ref={buttonRef}>button</button>
</div>
)
}
存储值----在useRef后写上值的类型
3.useContext
当useContext共享的值为已知值时 正常使用即可 但是当共享的值为future value时 要加上类型
创建Context
import React, {createContext, useState} from 'react'
type UserType = {
name: string
age: number
}
type UserContextType = {
userInfo: UserType | null
setUserInfo: React.Dispatch<React.SetStateAction<UserType | null>>
}
//给context添加类型
export const UserContext = createContext<UserContextType | null>(null)
//给Provider的props添加类型
export const UserContextProvider = ({children}: {children: React.ReactNode}) => {
//useState添加类型
const [userInfo, setUserInfo] = useState<UserType | null>(null)
return (
//填写共享值
<UserContext.Provider value={{userInfo, setUserInfo}}>
{children}
</UserContext.Provider>
)
}
包裹子组件
import React from 'react'
import {UserContextProvider} from './Context'
import Child from './Child'
export default function App() {
return (
<div>
App
<UserContextProvider>
<Child></Child>
</UserContextProvider>
</div>
)
}
子组件useState
import React, {useContext} from 'react'
import {UserContext} from './Context'
export default function Child() {
//useContext中填写context
const userContext = useContext(UserContext)
return (
<div>
<button onClick={() => userContext?.setUserInfo({name: '张三', age: 15})}>
login
</button>
<button onClick={() => userContext?.setUserInfo(null)}>logout</button>
<p>姓名:{userContext?.userInfo?.name}</p>
<p>年龄:{userContext?.userInfo?.age}</p>
</div>
)
}
总结:其实就是在context组件中给createContext provider等添加类型
4.useSelector
useSelector是在组件中获取redux的值的时候使用
useSelector(state<RootState>=>state.article)
3.在自己写的函数中的使用
4.在redux中的使用
ts结合redux使用 主要是给各种state action添加类型
在types/store.d.ts中存储的类型 其实主要都是各种action的type+RootState的类型
// redux相关的类型
import { ThunkAction } from 'redux-thunk'
import store from '../store'
import { Channel, Token, User, UserProfile } from './data'
// redux中store数据的类型
export type RootState = ReturnType<typeof store.getState>
// redux中所有action类型
type RootAction = LoginAction | ProfileAction | HomeAction
// redux异步action函数返回值类型
export type RootThunkAction = ThunkAction<void, RootState, unknown, RootAction>
// 相关模块的action类型:login home等
export type LoginAction = {
type: 'token/login'
payload: Token
} | {
type: 'login/logout'
}