​Ant Disign 4.0 升级实践扑街指南 (一)

  • 2020 年 3 月 13 日
  • 筆記

背景

我们都知道, AntD 最近喜提了4.0, 更新了许多新特性,看的我是心花怒放, 喜不自胜。更贴心的是还提供了升级工具,看了一些文章介绍说能三分钟升级。于是周六的时候, 懒觉我也不睡了, 跑到公司开始了升级之旅。

注:此篇文章仅是我个人升级的时候遇到的一些问题,不具代表性,仅供参考

正文

首先是从这篇文章开始的:

很多公众号也转发了这篇文章, 很吸引人, 我也想体验一下。

扑街第一步: antd4-codemod

看官方介绍:

一键转换!我滴龟龟, 也太好了吧!!

马上安排!

于是我敲下了第一行命令:

sudo npm i -g @ant-design/codemod-v4

全局安装了这个代码转换工具, 很顺利。

扑街第一步:antd4-codemod

运行 antd4-codemod src

控制台:

出师未捷身先死

问题不大, 我们老实人不怕这个。

缺少core-js, 那就装一个。

安装之后, 还是同样的报错。。。

一番搜索之后, 在一个不起眼的文章里找到了答案:

全局安装, 果然不报错core-js找不到了, 问题解决。

(中间也爆了其他的错, 花了不少时间,不过都一一解决了。)

直到又爆了新的错误:

搜索到一些答案:

按照文章中的提示,逐个修改,等待安装。

运行一下, 还是不行。。。

表情逐渐凝固。

这时候已经六七点了,看看外面, 天都黑了。

这第一步还没迈出去, 开始暴躁。

我是谁, 我在哪,我为什么要用这个 antd4-codemod...

冷静一下, 打了局农药单排,输了。

然后开始手动一个个改文件。

扑街第二步: Form initialValues

想着今天一定, 至少, 得改完一个页面看看。

就挑了个简单的, 一个Form表单页。

v3 与v4的表单差别还是挺大的。

Form v3 & v4

去除 Form.create

v4 的 Form 不再需要通过 Form.create() 创建上下文。Form 组件现在自带数据域,因而 getFieldDecorator 也不再需要,直接写入 Form.Item 即可:

// antd v3  const Demo = ({ form: { getFieldDecorator } }) => (    <Form>      <Form.Item>        {getFieldDecorator('username', {          rules: [{ required: true }],        })(<Input />)}      </Form.Item>    </Form>  );    const WrappedDemo = Form.create()(Demo);  复制代码

改成:

// antd v4  const Demo = () => (    <Form>      <Form.Item name="username" rules={[{ required: true }]}>        <Input />      </Form.Item>    </Form>  );

由于移除了 Form.create(),原本的 onFieldsChange 等方法移入 Form 中,通过 fields 对 Form 进行控制。

表单控制调整

Form 自带表单控制实体,如需要调用 form 方法,可以通过 Form.useForm() 创建 Form 实体进行操作:

// antd v3  const Demo = ({ form: { setFieldsValue } }) => {    React.useEffect(() => {      setFieldsValue({        username: 'Bamboo',      });    }, []);      return (      <Form>        <Form.Item>          {getFieldDecorator('username', {            rules: [{ required: true }],          })(<Input />)}        </Form.Item>      </Form>    );  };    const WrappedDemo = Form.create()(Demo);

改成:

// antd v4  const Demo = () => {    const [form] = Form.useForm();      React.useEffect(() => {      form.setFieldsValue({        username: 'Bamboo',      });    }, []);      return (      <Form form={form}>        <Form.Item name="username" rules={[{ required: true }]}>          <Input />        </Form.Item>      </Form>    );  };

有个很简单列表页里包含一个Form,点击按钮,查看数据。

codeOpen链接:codepen.io/scaukk/pen/…

提了个issue: github.com/ant-design/…

这个问题,一个热心网友说:

加一个effect 每次显示modal的时候重置, 这个resetFields重置的每次都是initialValue的值 你每次确定的时候重置的值其实都是上一次的, 所以不会变

偏右的回复:

resetFields 是重置回 initialValues 的值,并且 initialValues 只用于第一次初始化,不响应后续的变化,你需要转换一下思路:https://codepen.io/afc163-1472555193/pen/LYVjNWN?editors=0011

在官网中, 也找到了这样的描述:

在 v3 版本中,修改未操作的字段 initialValue 会同步更新字段值,这是一个 BUG。但是由于被长期作为一个 feature 使用,因而我们一直没有修复。在 v4 中,该 BUG 已被修复。initialValue 只有在初始化以及重置表单时生效。

所以, initialValue 只能作为组件初次挂载的时候生效。

偏右的做法和文档推荐的一致:

render: (text, record) => (    <span onClick={() => {      setVisible(true)      setRecord(record)      form.setFieldsValue({        name: record.name,      });    }}>      <a>查看</a>    </span>  ),  复制代码

不过这样子手动setFieldsValue比较麻烦, 我想了一下一下之后, 用了另一种方法是来解决这个问题。

新的办法:

把 Modal 单独抽出来, 把这里的form:

const [form] = Form.useForm();

随着组件的销毁一起销毁, 这样每次的数据就都是新的了, 完美。

Live Demo:

至此, 第一个页面就改完了。

结尾

后面还有好多个页面需要改,不过我认为这是值得的。

之后还会持续更新, 希望大家都能避开这些点。

图看不清楚的可以阅读原文。

希望本文对大家有所帮助。