try catch 是否能捕获异步的错误
const handelSubmit = async ({ cpassword, ...values}: {username: string, password: string, cpassword: string}) => {
if (cpassword !== values.password) {
onError(new Error('请确认两次密码是否一致'));
return;
}
try {
await run(register(values));
}
catch (e) {
onError(e as Error);
}
};
参考资料: https://blog.csdn.net/qq_43497320/article/details/122675328
Iterator
let a = [1, 2, 3]
for (o of a) {console.log('item', o)}
VM320:1 item 1
VM320:1 item 2
VM320:1 item 3
var i = a[Symbol.iterator]()
Array Iterator {}
i.next()
{value: 1, done: false}
i.next()
{value: 2, done: false}
i.next()
{value: 3, done: false}
i.next()
{value: undefined, done: true}
obj iterator 实现
const obj = {
data: ['hello', 'world'],
[Symbol.iterator] () {
let self = this;
let index = 0;
return {
next () {
if (index < self.data.length) {
return {
value: self.data[index++],
done: false,
}
}
else {
return {
value: undefined,
done: true,
}
}
}
}
}
};
for(o of obj) {
console.log(o)
}
// 语法:
Object.fromEntries(iterable)
将部署了iterator的转化为对象
Object.fromEntries() 执行与 Object.entries 互逆的操作
参考资料: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries
获取antd组件类型
import { Select } from "antd";
type SelectProps = React.ComponentProps<typeof Select>
interface IdSelectProps extends Omit<SelectProps, 'value' | 'onChange' | 'defaultOptionName' | 'options'> {
value: number
onChange: (value?: number) => void
defaultOptionName?: string
options?: {name: string, id: number}[]
}
惰性state
如果useState的初始值需要复杂的计算获得 ,则可以传入一个函数,
这个函数在组件渲染时会直接执行。
const [callback, setCallback] = useState(() => {
alert('init');
});
<Button onClick={() => setCallback(() => aleart('update lazy value'))}>click</Button>
因此不能用 useState 保存函数
因为无论是制定初始值还是在未来的更新函数中传入函数,都会直接执行,不能起到保存函数的结果。
!!注意: 使用以上方式保存函数,可能会引发无限循环,
如果你在一处函数中调用中调用了 setCallback!
那么 setCallback 里的函数直接执行会重渲,
而重渲时那一处函数调用又会重新调用 setCallback!
const APP = () => {
const retry = () => {
setCallback(() => run());
};
const run = async () => {
retry();
...
..
};
}
...
使用 useState 保存函数的正确做法
const const [callback, setCallback] = useState(() => () => {
alert('init');
});
<Button onClick={() => setCallback(() => () => aleart('update lazy value'))}>click</Button>
react-routerv6设置默认路由
<Link to={"kanban"}>看板</Link>
<Link to={"epic"}>任务组 </Link>
<Routes>
<Route path="/kanban" element={<KanbanScreen />} />
<Route path="/epic" element={<EpicScreen />} />
<Route path="*" element={<Navigate to={window.location.pathname + '/kanban '} replace />} />
</Routes>
如果 将navigate放于Routes 下面, 会陷入未知的最大更新深度错误。
<Route path="*" element={<Navigate to={window.location.pathname + '/kanban '} replace />} />
<Navigate to={window.location.pathname + '/kanban '}/>
const navaigate = useNavigate();
const location = window.location.pathname;
const getIncludes = (path: string) => {
return location.includes(path);
};
useMount(() => {
if (!getIncludes('kanban') || !getIncludes('epic')) {
navaigate(`${location}/kanban`);
}
});
解构的正确用法
const {run, ...result} = useSync<User[]>();
解构的值改名
const { mutateAsync: addKanban } = useAddKanban(useKanbansQueryKey());
Why-DId-You-Render
就像它的名字一样 你为什么render?
安装
npm install @welldone-software/why-did-you-render -D
import React from 'react';
if (process.env.NODE_ENV === 'development') {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React, {
trackAllPureComponents: false,
});
}
ProjectList.whyDidYouRender = true;
Cra 中 区分当前的环境,采用不同的环境变量
线上环境
项目根目录中新建
.env 文件
写入:
REACT_APP_API_URL = 'https://online.com'
本地环境
新建
.env.development
写入:
REACT_APP_API_URL = 'http://localhost:4001'
const api = process.env.REACT_APP_API_URL;
return window.fetch(`${api}/${endpoint}`, config);
修改项目主题色 craco
安装
npm i @craco/craco
/* 修改 package.json */
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
}
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: { '@primary-color': 'rgb(183, 139, 226)', '@font-size-base': '16px' },
javascriptEnabled: true,
},
},
},
},
],
};
v5自定义主题
import React from 'react';
import { ConfigProvider } from 'antd';
export default () => (
<ConfigProvider
theme={{
token: {
colorPrimary: '#00b96b',
},
}}
>
<MyApp />
</ConfigProvider>
);
https://ant-design.gitee.io/docs/react/use-with-create-react-app-cn