react+ts使用

240 阅读4分钟

本文适合会使用react以及了解ts语法的人
最近在学习react+ts在项目中的使用,走了几天弯路.说来奇怪,分开都能理解什么意思,可是react+ts一起用就不知道咋下手了.总结了一下这几天所理解的react+ts的使用,参考视频b站搬运视频

Getting started!

1.在组件中的使用

  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" />
    
  2. 在函数组件中的使用

    函数组件中主要在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 image.png

但是有时候 我们要获得的值是很复杂的,甚至有时候类型是不一样的 怎么解决呢?

image.png

此时 通过给useState设置类型即可解决

image.png

也可以使用类型断言

image.png

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后写上值的类型

image.png

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'
}