由一个小问题看出你可能没有真正理解hooks

595

之前写React一直用class生命周期得方式,最近又开始用hooks写项目,但是思维及习惯还是会按照以前生命周期得思维和方式去写代码,拿个最简单的列表查询页面举例,就会出现如下情况:

  const [tableData, setTableData] = useState<AbnormalOrderAppealList[]>([]);
  const [pageInfo, setPagination] = useState<PageInfo>({
    pageNum: 1,
    pageSize: 20,
    totalCount: 0,
  });
  const [formValue, setFormValue] = useState<{
    createTime: any;
    excludeScene: string;
  }>({
    createTime,
    excludeScene: '',
  });
  const [visible, setVisible] = useState(false);
  const [checkTableData, setCheckTableData] = useState<LogsType[] | undefined>([]);
  const searchParams = (params: { createTime: any; excludeScene: string }) => ({
    startTime: moment(params.createTime[0]).startOf('day').valueOf(),
    endTime: moment(params.createTime[1]).endOf('day').valueOf(),
    excludeScene: params.excludeScene,
  });
  // 获取列表数据
  const getList = useCallback(async (params: GetAppealRequest) => {
    const res = await getAppeal(params);
    setLoading(false);
    if (res?.code === 0) {
    	// 设置table数据
      setTableData(res?.data?.abnormalOrderAppealList || []);
      // 设置分页信息
      setPagination({
        pageNum: res?.data?.pageNum,
        pageSize: res?.data?.pageSize,
        totalCount: res?.data?.totalCount,
      });
    }
  }, []);
  // 初始化获取列表数据
  useEffect(() => {
    getList({
      ...searchParams(formValue),
      pageNum: 1,
      pageSize: 20,
    });
  }, []);
  // pageNum变化分页查询
  const handlePageChange = useCallback(
    (page: number) => {
      setLoading(true);
      setPagination({
        ...pageInfo,
        pageNum: page,
      });
      // 分页信息变化时候去获取列表数据
      getList({
        ...searchParams(formValue),
        pageNum: page,
        pageSize: pageInfo.pageSize,
      });
    },
    [pageInfo],
  );
  // pageSize变化
  const handlePagesizeChange = useCallback(
    (size: number) => {
      setLoading(true);
      setPagination({
        ...pageInfo,
        pageSize: size,
      });
      // pageSize变化时候去获取分页数据
      getList({
        ...searchParams(formValue),
        pageSize: size,
        pageNum: pageInfo.pageNum,
      });
    },
    [pageInfo],
  );
  // 点击查询按钮时候还去获取列表信息
  const onSubmit = (value: any, errors: any) => {
    if (errors) {
      return;
    }
    setLoading(true);
    getList({
      ...searchParams(value),
      pageNum: pageInfo.pageNum,
      pageSize: pageInfo.pageSize,
    });
  };

可以看到,getList初始化时候去调用、分页变化时候调用、点击查询时候也去调用,但其实useEffect第二个参数集合是干嘛的?监听[a,b,c] 初始化、a、b、c变化就会去执行第一个函数,所以其实根本不需要每次触发动作时候就去调用方法,而只需要把useEffect中的第二个参数用起来就好了,也就是每次分页/查询时候只要改变useEffect的第二个参数 数组中的值变化就可以触发getList方法了。

所以优化后代码如下:

 // 获取列表数据
  const getList = useCallback(async (params: GetAppealRequest) => {
    setLoading(true);
    const res = await getAppeal(params);
    if (res?.code === 0) {
      setTableData(res?.data?.abnormalOrderAppealList || []);
      setPagination({
        pageNum: res?.data?.pageNum,
        pageSize: res?.data?.pageSize,
        totalCount: res?.data?.totalCount,
      });
    }
    setLoading(false);
  }, []);
   // 初始化获取列表数据 && [pageInfo.pageNum, pageInfo.pageSize, formValue]变化时候触发getList()
  useEffect(() => {
    getList({
      ...searchParams(formValue),
      pageNum: pageInfo.pageNum,
      pageSize: pageInfo.pageSize,
    });
  }, [pageInfo.pageNum, pageInfo.pageSize, formValue]);
  // 分页查询
  const handlePageChange = useCallback(
    (page: number) => {
      setPagination({
        ...pageInfo,
        pageNum: page,
      });
    },
    [pageInfo],
  );
  const handlePagesizeChange = useCallback(
    (size: number) => {
      setPagination({
        ...pageInfo,
        pageSize: size,
      });
    },
    [pageInfo],
  );
  // 点击查询
  const onSubmit = (value: any, errors: any) => {
    if (errors) {
      return;
    }
    setPagination({
      ...pageInfo,
      pageNum: 1,
    });
    setFormValue(value);
  };

是不是简洁了一些,其实关键优化这里也不是光为了代码简洁,而是代码写成上面那种形式,可能本身对hooks理解的就不深刻,所以是为了实现某功能惯用以前的某些思维而实现业务逻辑,就是有这么个功能,我只是为了实现这个功能而用了这个api,实现不了再去打补丁实现它,这就违背的本身的设计初衷。

感受

其实文中提到的也不能算是bug或者就能说明什么问题,虽然看api文档时候也有注意到这类细节,或者必须要用这个第二个参数时候也能想起来用,但有时候不是必须要用的场景还是思维却没有真正转变过来,习惯去用以前class的思维去写hooks,然后突然某个瞬间只是突然明白过来了什么东西,但又好像这个也没什么 的感觉。有时候api看了,demo跑了,项目中用到了就是真的会了么,可能也不一定是会了,有些东西还是要思考要优化要多问几个为什么才能真正弄明白。

其实这个小的点还是有点不太敢发文章出来,因为好像没有什么难度,只是自己的一个小感受而已,但是又觉得好像需要记录下来