Ant Design Pro - 實踐React Hooks - 頁面

背景

React Hooks目前是React社區最煊赫一時的新技術,咱們準備追一下熱度,在當前的項目中實踐一下Hooks技術。
咱們的項目使用的腳手架是Ant Design Pro 2.0,初步想法是把現有的一個有狀態頁面組件重構成Hooks函數組件。javascript

設計

動手以前,先理一下思路,用Hook函數重構的話,須要調整哪些部分:html

  • 組件類要拆解成Hooks函數
  • 組件狀態改爲Hooks狀態
  • 類屬性改爲Hooks函數本地變量
  • 類方法改爲Hooks函數的嵌套函數,可公用的也能夠做爲Hooks函數平級的函數

再理一下過程當中的問題:java

  • 函數和類不同,它的this是由調用方決定的,是不肯定的,因此不要使用this(Hooks函數裏面也不必用this)。
  • 沒有this,就須要用傳參了,Hooks函數就是props轉遞。
  • Dva的使用,Ant Design Pro使用的Dva來管理數據(裏面封裝的是Redux),這裏咱們仍是能夠繼續使用,經過connect把Redux管理的model數據注入props。數組

    這裏有個小知識點,組件類的model注入,使用了註解形式的裝飾器,函數是不能使用裝飾器的,因此須要咱們手工注入。 理解一點:這裏的裝飾器就是高階函數
  • 狀態共享,Hooks狀態如何共享給其餘Hooks函數或普通函數?Hooks狀態聲明時會返回:狀態、修改此狀態的方法,這兩個返回值是能夠傳遞和共享的app

    這裏也補充一個小知識,咱們是能夠聲明一個服務類的Hooks,而後把狀態和狀態修改器返回來,這個是能夠共享和傳遞的,能夠實現相似全局狀態管理器的功能,Hooks也提供了額外的輔助方法:useReducer。這裏能夠深刻去學習一下。

解決了這些問題,咱們就能夠實踐了。ide

實現

咱們拆成了兩個Hooks組件:分頁列表 + 查詢表單,來看看最終實現的代碼。函數

入口 - 分頁列表Hooks組件

function TableList(props) {
  const {
    dispatch,
    account: { accountList },
    loading,
  } = props;

  const [formValues, setFormValues] = useState({});
  const [selectedRows] = useState([]);

  const columns = [
    {
      title: '序號',
      dataIndex: '_index',
    },
    {
      title: '帳戶名稱',
      dataIndex: 'accountName',
    },
  ];

  function handleSearch(e) {
    e && e.preventDefault();
    const { form } = props;

    form.validateFields((err, fieldsValue) => {
      if (err) return;

      dispatch({
        type: 'account/accountList',
        payload: fieldsValue,
      });
    });
  }

  function handleStandardTableChange(pagination, filtersArg, sorter) {
    const filters = Object.keys(filtersArg).reduce((obj, key) => {
      const newObj = { ...obj };
      newObj[key] = getValue(filtersArg[key]);
      return newObj;
    }, {});

    const params = {
      pageNumber: pagination.current,
      pageSize: pagination.pageSize,
      ...formValues,
      ...filters,
    };
    if (sorter.field) {
      params.sort = sorter.order === 'ascend' ? 'asc' : 'desc';
    }

    dispatch({
      type: 'account/accountList',
      payload: params,
    });
  }

  useEffect(() => {
    dispatch({
      type: 'account/clear',
    });
    // 自動查詢
    handleSearch();
  }, []);

  return (
    <PageHeaderWrapper>
      <Card bordered={false}>
        <div className={styles.tableList}>
          <div className={styles.tableListForm}>
            <SearchForm formValues={formValues} handleSearch={handleSearch} {...props} />
          </div>
          <StandardTable
            loading={loading}
            data={accountList}
            columns={columns}
            rowKey="_index"
            selectedRows={selectedRows}
            hideAlert
            disablePagination={false}
            onChange={handleStandardTableChange}
          />
        </div>
      </Card>
    </PageHeaderWrapper>
  );
}

const tableList = connect(({ accountaging, loading }) => ({
  accountaging,
  loading: loading.models.accountaging,
}))(Form.create()(TableList));

export default tableList;

這裏咱們注意幾個點:學習

  • props咱們是透傳給列表查詢表單的。
  • 查詢方法也是傳過去的。
  • 存放表單值的狀態是聲明在列表組件,傳給表單組件。
  • 這裏的userEffect實現了以前ComponentDisMount的功能,注意:依賴傳入了一個空數組,這裏表示不依賴任何狀態,因此只會在初次加載時執行,不然會出現死循環
  • 組件導出前,有個model和form的注入。

列表查詢表單

function SearchForm(props) {
  const {
    account: { accountList },
    form,
    formValues,
    handleSearch,
  } = props;
  const { getFieldDecorator } = form;

  return (
    <Form onSubmit={handleSearch} layout="inline">
      <Row gutter={16} justify="start">
        <Col xl={8} md={12} sm={24}>
          <FormItem labelCol={{ span: 6 }} wrapperCol={{ span: 16 }} label="帳戶名稱">
            {getFieldDecorator('accountName', {
              initialValue: '',
            })(<Input placeholder="帳戶名稱" />)}
          </FormItem>
        </Col>
        <Col xl={8} md={24}>
          <Button className="fun-button" type="primary" htmlType="submit">
            查詢
          </Button>
        </Col>
      </Row>
    </Form>
  );
}

表單組件這塊,東西很少,理解props就好。this

想法

其實整個實現下來,並不難。可是還有些問題須要咱們考慮一下:spa

  • 使用Hooks以後,帶來了哪些改變?
  • 代碼邏輯是否是更優了?
  • 代碼結構是否清晰?
  • 什麼樣是最佳實踐?

歡迎討論。

相關文章
相關標籤/搜索