22-december-2th


try catch 是否能捕获异步的错误

// 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);
  }
};

// 但如果去掉await就不能捕获异步错误了  待深究
参考资料: https://blog.csdn.net/qq_43497320/article/details/122675328

Iterator

/**
* 
* [] 、 {} 、Map 都是部署了 Iterator 的,
*
* 而部署了 Iterator 的 ,都可以使用 for ... of 进行遍历
*/

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 {} // 这里是var i 的结果; Array Iterator里有个next方法

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) // hello world
    }

Object.formEntries()

// 语法: 

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";
  
// 这样就取得了 组件 Select 的全部类型
type SelectProps = React.ComponentProps<typeof Select>
  
// 在封装组件时 可能会按照自己的定义指定组件类型,那么这时将两种类型合并就会有冲突

// 于是删除 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 '}/>
// 其他做法 js 跳转  更繁琐

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[]>();

// 只拿出需要用到的,剩下的return 出去 ,直接给组件使用

解构的值改名

// 改名之后使得变量、函数更加符合组件整体业务逻辑,见名知意;同时也避免变量重名

const { mutateAsync: addKanban } = useAddKanban(useKanbansQueryKey());

Why-DId-You-Render

就像它的名字一样  你为什么render?

安装

npm install @welldone-software/why-did-you-render -D
// 在 src目录下新建 wdyr.js 写入

import React from 'react';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    trackAllPureComponents: false, // 这里不监视所有组件
  });
}

// 在index.tsx 引入 wdyr.js
// 监视单个组件

ProjectList.whyDidYouRender = true;

// 这样就能在控制台看到多次render的信息

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;

// 这里 react 会自动判断当前处于什么环境,选择什么环境变量

return window.fetch(`${api}/${endpoint}`, config)// 目前在cra中可用,其他项目应该也可

修改项目主题色 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",
}
// 项目根目录创建

/* craco.config.js */
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,
          },
        },
      },
    },
  ],
};

// 不知为何 颜色配置 在v4 生效、v5不生效

v5自定义主题

// 这样也能修改项目的 primary color 

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

文章作者: KarlFranz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 reprint policy. If reproduced, please indicate source KarlFranz !
评论
  目录