2022年1-2月工作总结

React

数据透传,虽然使用了 props 进行层层传递,但是应该使用 context 进行透传。

避免过度使用 redux。

TypeScript

Array.includes

参考链接:https://fettblog.eu/typescript-array-includes/

export const ArrayUtils = {
  includes<T extends U, U>(arr: ReadonlyArray<T>, el: U): el is T {
    return arr.includes(el as T);
  },
} as const;

工具函数

使用子集与超集进行对比,因为后端传值和前端传给后端的数据存在些微差异,后端可能会多传一些值,所以利用这个方法进行对比,判断共同的属性值是否相同。

如果两个对象的属性相同只用比较值是否相同,可以使用 loadsh 的 isEqual 函数

type BaseValue = { [key: string]: string[] | number[] | string | number };
/**
 * 判断不相等,只判断相交的对象属性值是否相同,会深度对比每个对象中的属性值
 * @param base 子集
 * @param other 超集
 * @returns
 */
export const isDiffByPart = <
  T extends { [key: string]: string[] | number[] | string | number | BaseValue }
>(
  base: T,
  other: T
): boolean => {
  return Object.keys(base).some((key) => {
    const baseItem = base[key];
    const otherItem = other[key];
    if (baseItem && otherItem && !isEqual(baseItem, otherItem)) {
      if (typeof baseItem !== typeof otherItem) {
        return true;
      }
      if (typeof baseItem === 'number' || typeof baseItem === 'string') {
        return true;
      }
      if (
        typeof baseItem === 'object' &&
        typeof otherItem === 'object' &&
        baseItem?.length === otherItem?.length
      ) {
        return isDiffByPart(baseItem as T, otherItem as T);
      }
      return true;
    }
    return false;
  });
};

总结与反思

组件

  1. 将重复的组件抽出来,可以做一些 UI 组件。

CR 问题

  1. 文件嵌套过深,多个同名文件容易产生代码的理解成本。如果是一个页面的常量和类型尽量写在一个文件中,避免一个目录下一个常量和类型文件。

    一般来讲在页面这一级集中处理下面组件、常量、和工具方法可以满足大部分需求,更方便统一维护。

  2. 相对路径层级过深应使用绝对路径进行替换。

思想

有一点点对项目中引入 npm 包有点抵触和抗拒,会觉得容易引入麻烦或者说无用的包,后期还要优化掉的包,从而使用了很奇怪的代码写法,虽然奇怪的代码写法在后期重新改了,但是初期的代码设计还有有点糟糕。

因为推崇使用 await-to-js 库,但是又觉得没有必要专门导入这个库进来。所以使用了比较 hack 的方式:在 promise 函数返回的时候手动返回 [error, res] 格式,这样增加了代码理解成本,不能一下子 get 到为什么要这样写以及这样写的背景。

Await-to-js 库主要是为了避免 try-catch 地狱的问题(就是 try-catch 使用的太多了)

// shit code
// 想的是 handleCurrentStepSave 的代码调用返回的是 [error, res] 的格式
onSaveAndNext = async () => {
    this.handleCurrentStepSave()
      .then((res) => {
        if (Array.isArray(res) && res[0]) {
          return;
        }
        const nextStep = this.ruleConfigStepList[this.state.currentRuleConfigStepIndex].nextStep;
        if (nextStep) {
          this.setState({
            currentRuleConfigStepIndex: this.ruleConfigStep[nextStep].index,
          });
        } else {
          // 最后一步没有 nextStep
          this.props.dispatch({
            type: 'routerJumpModal/setIsSaved',
            payload: true,
          });
        }
      })
      .catch((err) => {
        console.log('handleCurrentStepSave: ', err);
        // Sentry.captureException(err);
      });
  };

// 改进
onSaveAndNext = () => {
    this.handleCurrentStepSave()
      .then(() => {
        const nextStep = this.ruleConfigStepList[this.state.currentRuleConfigStepIndex].nextStep;
        if (nextStep) {
          this.setState({
            currentRuleConfigStepIndex: this.ruleConfigStep[nextStep].index,
          });
        } else {
          // 最后一步没有 nextStep
          this.props.dispatch({
            type: 'routerJumpModal/setIsSaved',
            payload: true,
          });
        }
      })
      .catch((err) => {
        // 如果 err 是数组表示表单校验未通过
        if (isArray(err)) {
          return;
        }
        Sentry.captureException(err);
      });
  };