04月11, 2019

react hooks & antd踩坑记

手头这个项目做得差不多了。分享一下碰到的一些坑。

一个常见的错误

Can't perform a React state update on an unmounted component.

项目中代码里面的写法大概是这样的:

import { useStore } from 'easy-peasy';

const Box = () => {
  return (
    <div>
      <Button onClick={() => {
           // 在这里全局去改变`globalLoading`
       }}>点我</Button>
    </div>
  )
};

const Wrapper = () => {

  const globalLoading = useStore((state) => state.common.globalLoading);

  return (
    <Spin spinning={globalLoading} size="large" >
      <Box />
    </Spin>
  )
}

此Bug的原因是:由于Wrapper组件的外层spinning属性发现变化,所以会重渲染整个容器,然后就把Box组件销毁了,那么如果在Box组件里面如果还有其他的状态改变,就会发生错误。

解决的方式很简单,因为Box组件没有任何的props改变,所以它不应该被重渲染。

const Box = memo(() => {
  return (
    <div>
       { /* */ }
    </div>
  )
});

memo有些类似class component里面的PureComponent

useEffect不能直接使用async

注意这样写是错误的:

useEffect(async () => {
  const result = await API.getXX();
  console.log(result);
}, []);

原因在于:它返回的结果不能是promise。

正确的写法如下:

async function fetchXX() {
  const result = await API.getXX();
  console.log(result);
}

useEffect(() => {
  fetchXX();
}, []);

antd form

拆组件

先看一下界面吧:

alt

这三个form item,其实都可以拆出去。因为它们的数据来自于后端。基至于说,这三个还会有依赖关系:导入应用会依赖环境的数据,选择模板会依赖上面两个的数据。

alt

props

getFieldDecorator包裹的组件,都可以拿到以下两个属性:

  • value
  • onChange

value的值为initialValue的值,默认为undefined。onChange就是用来处理组件和form的传值。

searchEnv的代码来说:

import React, { useState, useEffect } from 'react';
import { Select } from 'antd';

import API from '@/request';

const Option = Select.Option;

async function fetchEnvList(setEnvList) {
  const envList = await API.getListCloudEnv();
  setEnvList(envList);
}

const SearchEnv = (props) => {
  const [envList, setEnvList] = useState([]);
  const { value, onChange } = props;

  useEffect(() => {
    fetchEnvList(setEnvList);
  }, []);

  return (
    <Select
      style={{width: 200}}
      defaultValue={value}
      onChange={(value) => {
        onChange(value); // 重新给到form组件
      }}
    >
      <Option value="">请选择</Option>
      {
        envList.map(env => {
          return <Option key={env.envId}>{env.envName}</Option>
        })
      }
    </Select>
  )
};

export default SearchEnv;

解决报错

上面的代码,看似没啥问题了。但事实上打开控制台会有以下的错误:

alt

OK,也就是说必须用React.forwardRef来实现。(当然你用class component也是OK,只是我这边不再使用了)

级联

这个是我碰到的一个很大的坑。翻来覆去,折腾了很多代码,才捣鼓出来。

先说问题:

导入环境会有多个值:请选择dev环境test环境。用户选择dev环境时,会根据ID去ajax请求拿到应用列表,假设导入应用的选项有:请选择应用一应用二。用户选择了应用一,然后用户再回到导入环境,选择test环境,此时导入应用应该回到请选择,而不是依旧应用一

解决方案:使用setFieldsValue

<SearchEnv onSelectChange={() => {
  const appId = getFieldValue('cloudApp');
  if (appId !== undefined) {
    setFieldsValue({
      cloudApp: ""
    })
  }
}} />

alt

这里我说一下,为什么要判断appId !== undefined,因为我一开始应用列表是不显示的:

alt

本文链接:www.my-fe.pub/post/react-hooks-and-antd.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。