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:
至此, 第一個頁面就改完了。
結尾
後面還有好多個頁面需要改,不過我認為這是值得的。
之後還會持續更新
, 希望大家都能避開這些點。
圖看不清楚的可以閱讀原文。
希望本文對大家有所幫助。