【react框架】记录一些TypeScript在React中的写法,不怕老年痴呆了

前言

自从GPT出现后,这篇文章就显得没啥作用了,这也是这这篇文章不更新的原因。以后我就记录一些使用心得和注意事项了。


心得

用import type去引入类型定义

例如:

import type { MyThing } from "./some-module.ts";

import也可以导入,和import type有什么区别呢?可以详看这篇文章:import 和 import type的区别

我这里也补充一个原因,在一些第三方库中,他们的package.json中有个types字段,值为这个库的tpye定义文件总入口,也就是说当我们用了import type去引入类型的时候,会根据package.json中types指定的文件去找对应的类型。


类型定义文件用.d.ts去命名

例如utils.d.ts,我看第三方库和网上其他人都这么写,不过也有写.ts的。

  • .ts文件:可以编译成.js文件的,可以写类型代码又可以执行代码
  • .d.ts文件:只能写类型代码,不会生成.js文件,也不能写可以执行的代码,只能提供类型。

第三方库标签的函数默认参数类型定义用它自带的

但又有些第三方库的标签不能用react内置的,只能从库里去引入,例如@dnd-kit/core

import {
  DndContext,
  DragEndEvent,
} from '@dnd-kit/core'


function handleDragEnd(event: DragEndEvent) {
  // ...
}

return (
  <DndContext onDragEnd={handleDragEnd}>
    <SortableContext>
      {children}
    </SortableContext>
  </DndContext>
)

但大多数时候,你是不知道具体的类型要引入那个,此时可以通过编辑器的提示去对应引入,例如handleDragEnd中的event会提示,需要DragEndEvent类型,这时你再去引入即可。


枚举用普通的写法即可

别写一些花里胡哨的写法,就正经写最普通的写法即可,编译出来就编译出来,几十个枚举没多少代码量的:

enum SLIDE_ENV{
    APPLE = 'A',
    FISH = 'F'
}

也不要写常数枚举,运行时打印不出来的。


接口返参怎么处理

可以详细看我这篇文章【场景方案】如何去设计并二次封装一个好用的axios,给你提供一个另类写法,另加一些思考


类型定义

FC定义组件类型

这个是React中的一种函数组件类型,一般我们写函数组件的时候使用它来定义类型:

import React, { FC } from 'react'

const Home: FC = () => {
  return (
    <div></div>
  )
}

export default Home

stlye类型定义

const style = useMemo(
  () =>
    ({
      ...baseStyle,
    } as React.CSSProperties),
  []
);

useState用泛型定义类型即可

const [selectedIds, setSelectedIds] = useState<string[]>([])
const [user, setUser] = useState<User | null>(null) // 给一个泛型,设定初值和后值

useRef类型定义的注意事项

// div
const containerRef = useRef<HTMLDivElement>(null)
// 一些第三方库组件可以这样
const scrollbarRef = useRef<InstanceType<typeof Scrollbars>>(null);

props推荐使用Partial

因为咱们组件定义的props属性并不是每一个参数都一定会传入的,所以使用Partial刚刚好:

type PropsType = {
  isStar: boolean
  setSelectedComponentId: (id: string) => void // 函数
  children: JSX.Element | JSX.Element[] // 传入的是JSX
  items: Array<{ id: string; [key: string]: any }> // 数组
}

const Header: FC = (props: Partial<PropsType> = {}) => {
	// ...
}

写普通函数也可以这样:

function fn(opt: Partial<PropsType> = {}){
	// ...
}

但如果想要严格限制就不用Partial:

type PropsType = {
  isStar: boolean
  isDeleted: boolean
}

const Header: FC = (props: PropsType) => {
	// ...
}

// 或者
const Header: FC<PropsType> = props => {
	// ...
}

// 或者
const Header: FC<PropsType> = (props: PropsType) => {
	// ...
}

内置标签的函数默认参数类型定义用react内置的

例如input标签等,会有个onChange事件,默认参数可以用ChangeEvent这样定义:

import React, { FC, useState, ChangeEvent } from 'react'

function handleChange(event: ChangeEvent<HTMLInputElement>) {
	// ...
}

<input
  onChange={handleChange}
/>

其实有些第三方库的事件也可以用react内置的,例如antd的Input标签也是可以用的。

其他例子:

const YourComponent: React.FC = () => {
  const handleWheel = (e: WheelEvent<HTMLDivElement>) => {
    // 这里写你的滚动事件处理逻辑
  };

  return <div onWheel={handleWheel}>滚动我!</div>;
};

把变量显示在页面上

一般情况下对象类型的变量无法通过JSX显示到页面上,我们可以用一个简单的函数实现转换:

export function str(o: unknown): React.ReactNode {
  return typeof o === "object"
    ? JSON.stringify(o, null, 2)
    : (o as React.ReactNode);
}

然后在JSX中就可以使用了:

<td>
  {str(value)}
</td>

合并TailwindCss的类名

在使用TailwindCss时,有时候我们需要在类名中用一些JS表达式去条件选择类名,那么我们可以封装一个公共函数:

import clsx from "clsx";
import { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

使用:

className={cn(
  props.currentChat === null
    ? "bg-gray-50 text-indigo-600"
    : "text-gray-700 hover:text-indigo-600 hover:bg-gray-50",
  "group flex gap-x-3 rounded-md -mx-2 p-2 text-sm leading-6 font-semibold cursor-pointer"
)}

上传文件类型定义

const [files, setFiles] = useState<File[]>([]);

把setState传入props

拿上面的setFiles传入来举例:

setFiles: React.Dispatch<React.SetStateAction<File[]>>;

未完待续

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值