新建项目
1 2 3 4 5
| npx create-react-app my-app --template typescript
# or
yarn create react-app my-app --template typescript
|
安装 react-router
1 2 3 4 5 6
| npm install --save react-router-dom yarn add react-router-dom
npm i -D @types/react-router-dom
yarn add @types/react-router-dom -D
|
Ts 中别名的设置
很多时候引入模块想把src
设置为@
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { defineConfig } from 'vite' import path from 'path'; export default defineConfig({ resolve: { alias: { "@": path.resolve(__dirname, "src"), }, }, }
"baseUrl": "./", "paths": { "@/*": ["src/*"] }
|
useState
对于存储string
类型的 state,在useState
右边加上<string>
即可:
1 2
| const [input, setInput] = useState<string>("");
|
如果要存储数组,就要用interface
1 2 3 4 5
| [ { id: "xxxx", content: "xxxxxxx", isDone: false }, { id: "xxxx", content: "xxxxxxx", isDone: false }, { id: "xxxx", content: "xxxxxxx", isDone: false }, ];
|
1 2 3 4 5 6
| interface TaskObj { id: string; content: string; isDone: boolean; } const [task, setTask] = useState<TaskObj[]>([]);
|
继承父组件中 state 并有自己的初始值
父子传参
js 中传参直接在子组件上写,子组件通过props
接收
1
| <Doing doing={doing} setTask={setTask} />
|
但是 ts 会报错,因为子组件并没有满足传递参数的接口,需要定义接口
1 2 3 4 5 6 7 8 9
|
interface DoingProps { doing: TaskObj[]; setTask: Function; } const Doing: React.FC<DoingProps> = ({doing,setTask}) => {...}
|
使用 context
尽量使用 context,使用 provider 去替代 props.
类型断言
拿输入框DOM
节点的时候
1 2 3 4 5
| const inputNode: HTMLInputELement = document.getELementById(`${id}`);
const inputNode: HTMLInputElement = document.getElementById( `${id}` ) as HTMLInputElement;
|
事件
常用的 React 事件类型
- React.MouseEvent - 点击事件
- React.KeyboardEvent - 键盘事件
- React.DragEvent - 拖拽事件
- React.FocusEvent - 焦点事件
- React.ChangeEvent - 表单域值变更事件
- React.FormEvent - 表单提交事件
- React.WheelEvent - 鼠标滚动事件
- React.TouchEvent - 触摸事件
注意,有的不能加 react,因为加了 React 是合成事件,不加是原生事件.
键盘事件
1
| const addTodo = (e: React.KeyboardEvent<HTMLInputElement>): void => {...}
|
输入事件
1 2 3 4 5 6 7 8 9 10 11
| <input ref={editInput} onBlur={(e: React.FocusEvent<HTMLInputElement>) => onBlurEdit(e)} className="text-edit" style={{ display: state.onEdit ? "block" : "none" }} value={todo.content} onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleTodoTextEdit(e, todo) } onKeyPress={(e: React.KeyboardEvent<HTMLInputElement>) => submitEditText(e)} />
|
e 的值可以是(e.target as HTMLInputElement).value
.
细节的注意
泛型
泛型在类型或者接口后,是传入参数的约束.也就是说传入的参数是在这个泛型之内的.
返回类型
jsx 的返回类型是ReactElement
node 元素的返回类型是ReactNode
技巧
useState 中设置 setState 中的方法可以将参数解构,简化浅拷贝
1
| onChange={e => setParam(...param, e.target.value)}
|
fetch 方法返回的是异步可以用 async 处理
1 2 3 4 5
| fetch("").then(async (res) => { if (res.ok) { setList(await res.json()); } });
|
修改值时可以先将该值拷贝,修改拷贝值,return 出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const useArray = <T></T>(initialArray: T[]) => { const [value, setValue] = useState(initialArray)
return { value, setValue, add: (item: V) => { setValue([...item, value]) }, clear: () => setValue([]), removeIndex: (index: number) => { const copy = [...value] copy.splice(index,1) setValue(copy) } } }
|
自定义 http
当一个参数有默认值时,参数内自动变为可选
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 39 40 41
| export const http = ( endpoint: string, { data, token, headers, ...customConfig }: Config = {} ) => { const config = { method: "GET", headers: { Authorization: token ? `Bearer ${token}` : "", "Content-Type": data ? "applcation/json" : "", }, ...customConfig, };
if (config.method.toUpperCase() === "GET") { endpoint += `?${qs.stringify(data)}`; } else { config.body = JSON.stringify(data || {}); }
return window.fetch(`${apiUrl}/${endpoint}`, config).then(async (res) => { if (res.status === 401) { await auth.logout(); window.location.reload(); return Promise.reject({ message: "请重新登录" }); }
const data = await res.json(); if (res.ok) { return data; } else { return Promise.reject(data); } }); };
export const useHttp = () => { const { user } = useAuth(); return (...[endpoint, config]: Parameters<typeof http>) => http(endpoint, { ...config, token: user?.token }); };
|
关于 svg 的引入问题
cra 虽然声明了 svg 作为模块可以引入,但是仍会报错.
解决方法:
新建src/react-app-env.d.ts