React Hooks 初使用

React Hooks 使用

使用感想

  1. 更加利于阅读的代码
  2. 代码量更少
  3. 使用更方便
  4. 由原代码修改为 Hooks 代码也很方便

经验

componentDidMount 和 componentDidUpdate 的逻辑不同;
可以使用 带第二个参数的 useEffects 来表示 componentDidMount

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

代码对比

总体代码量对比

文件名 代码行数 使用Hooks后代码行数
index.js 330 249
DataTable.js 179 118
SearchForm.js 110 97
ActualValueEditModal.js 233 145

执行 cat dir/**.* | egrep -v '^\s*$|^.{1}$' | wc -l 去除空行 和 源代码中样式文件代码数

修改前代码行数 修改后代码行数
767 557

index.js 文件代码对比

修改前的代码

/**
 * 基础数据管理
 * BasicData
 * @date 2019-05-28
 * @copyright 2019-05-28 © HAND
 */

import React, {Component} from 'react';
import {connect} from 'dva';
import {Bind} from 'lodash-decorators';
import {Button, Popconfirm} from 'hzero-ui';
import queryString from "query-string";

import {Content, Header} from 'components/Page'

import intl from 'utils/intl';
import notification from 'utils/notification';
import formatterCollections from "utils/intl/formatterCollections";
import {openTab} from "utils/menuTab";

import {getFieldsValueByRef} from '@/utils/utils';

import SearchForm from "./SearchForm";
import DataTable from "./DataTable";
import ActualValueEditModal from "./ActualValueEditModal";

import styles from './styles.less';

const id = 'id';

@connect(
  mapStateToProps,
  mapDispatchToProps
)
@formatterCollections({code: ['hnlp.basicData']})
export default class BasicData extends Component {
  // #endregion
  constructor(props) {
    super(props);
    this.searchFormRef = React.createRef();
    this.state = {
      selectedRows: [],
      selectedRowKeys: [],
      editActualValueModalVisible: false,
      // pagination: {}, // 存储分页信息
    };
  }

  componentDidMount() {
    const {init} = this.props;
    init();
    this.handleSearch();
  }

  // #region gen functions


  reload() {
    const {pagination} = this.state;
    this.handleSearch(pagination);
  }

  // #region data inv
  handleSearch(pagination = {}) {
    const {query} = this.props;
    const queryData = getFieldsValueByRef(this.searchFormRef);
    this.setState({
      pagination,
      selectedRows: [],
      selectedRowKeys: [],
    });
    return query({
      query: {...queryData, ...pagination},
    })
  }

  // #end

  // #region Header Btn Functions

  /**
   * 批量导入
   */
  @Bind()
  handleBatchImport() {
    openTab({
      key: '/hnlp/data-import/HNLP.BASIC_DATA',
      search: queryString.stringify({
        key: '/hnlp/data-import/HNLP.BASIC_DATA',
        title: 'hzero.common.title.batchImport',
        action: intl.get('hzero.common.title.batchImport').d('批量导入'),
      }),
    });
  }

  @Bind()
  async handleDelBtnClick() {
    const {selectedRows = []} = this.state;
    const {removeBatch} = this.props;
    removeBatch({records: selectedRows})
      .then(res => {
        if (res) {
          notification.success();
          this.reload();
        }
      })
  }

  delBtnDisabled() {
    const {selectedRows = []} = this.state;
    return selectedRows.length === 0;
  }

  // #endregion

  // #region DataTable
  @Bind()
  handleRowSelectionChange({selectedRows = [], selectedRowKeys = []}) {
    this.setState({
      selectedRowKeys,
      selectedRows,
    })
  }

  @Bind()
  handleRecordEdit(record) {
    this.setState({
      editActualValueModalVisible: true,
      editRecord: record,
    });
  }

  @Bind()
  handleTableChange(page, filter, sort) {
    this.handleSearch({page, sort});
  }

  // #endregion

  // #region EditFormModal
  @Bind()
  handleRecordActualValueEditOk(record) {
    const {update} = this.props;
    const {editRecord} = this.state;
    update({record: {...editRecord, ...record}, id: editRecord[id]}).then((res) => {
      if (res) {
        notification.success();
        this.closeEditFormModal();
        this.reload();
      }
    })
  }

  @Bind()
  handleRecordActualValueEditCancel() {
    this.closeEditFormModal();
  }

  closeEditFormModal() {
    this.setState({
      editActualValueModalVisible: false,
      editRecord: {},
    });
  }

  // #endregion

  // #region SearchForm
  @Bind()
  handleSearchFormSubmit() {
    this.handleSearch();
  }

  // #endregion

  render() {
    const {
      dataSource,
      pagination,
      removeBatchLoading,
      updateLoading,
      queryLoading,
    } = this.props;
    const {
      selectedRowKeys,
      editActualValueModalVisible = false,
      editRecord,
    } = this.state;
    const languageMessage = this.getLanguageMessage();
    return (
      <React.Fragment>
        <Header>
          <Popconfirm
            title={languageMessage.common.message.confirm.remove}
            onConfirm={this.handleDelBtnClick}
          >
            <Button
              disabled={this.delBtnDisabled()}
              loading={removeBatchLoading}
              type="primary"
            >
              {languageMessage.common.btn.del}
            </Button>
          </Popconfirm>
          <Button icon="import" onClick={this.handleBatchImport}>
            {languageMessage.common.btn.batchImport}
          </Button>
        </Header>
        <Content className={styles['hnlp-basic-data']}>
          <SearchForm
            languageMessage={languageMessage}
            wrappedComponentRef={this.searchFormRef}
            onSearch={this.handleSearchFormSubmit}
            queryLoading={queryLoading}
            removeBatchLoading={removeBatchLoading}
          />
          <DataTable
            onRowSelectionChange={this.handleRowSelectionChange}
            onRecordActualValueEdit={this.handleRecordEdit}
            onChange={this.handleTableChange}
            dataSource={dataSource}
            pagination={pagination}
            languageMessage={languageMessage}
            selectedRowKeys={selectedRowKeys}
            queryLoading={queryLoading}
            removeBatchLoading={removeBatchLoading}
          />
          <ActualValueEditModal
            languageMessage={languageMessage}
            visible={editActualValueModalVisible}
            record={editRecord}
            onOk={this.handleRecordActualValueEditOk}
            onCancel={this.handleRecordActualValueEditCancel}
            updateLoading={updateLoading}
          />
        </Content>
      </React.Fragment>
    );
  }
}

function mapStateToProps({nlpBasicData = {}, loading = {}}) {
  const {
    dataSource,
    pagination,
    enums,
  } = nlpBasicData;
  return {
    dataSource,
    pagination,
    enums,
    initLoading: loading.effects['nlpBasicData/init'],
    removeBatchLoading: loading.effects['nlpBasicData/removeBatch'],
    updateLoading: loading.effects['nlpBasicData/update'],
    queryLoading: loading.effects['nlpBasicData/query'],
  };
}

function mapDispatchToProps(dispatch) {
  return {
    init: (payload) => {
      return dispatch({
        type: 'nlpBasicData/init',
        payload,
      })
    },
    removeBatch: (payload) => {
      return dispatch({
        type: 'nlpBasicData/removeBatch',
        payload,
      });
    },
    update: (payload) => {
      return dispatch({
        type: 'nlpBasicData/update',
        payload,
      });
    },
    query: (payload) => {
      return dispatch({
        type: 'nlpBasicData/query',
        payload,
      });
    },
  };
}

修改后的代码, 删除一些无关代码

/**
 * BasicData
 * @date 2019-05-23
 * @copyright 2019 © HAND
 */

import React, {useEffect, useRef, useState} from 'react';
import {Popconfirm, Button} from 'hzero-ui'
import {connect} from 'dva';

import {Content, Header} from 'components/Page';

import formatterCollections from "utils/intl/formatterCollections";
import intl from 'utils/intl';
import notification from 'utils/notification';

import SearchForm from "./SearchForm";
import DataTable from "./DataTable";
import ActualValueEditModal from "./ActualValueEditModal";

/**
 * 通过表单的ref获取表单的数据
 * @param {React.ref} ref
 * @returns {{}|*}
 */
export function getFieldsValueByRef(ref) {
  if (ref.current) {
    const form = ref.current;
    return form.getFieldsValue();
  }
  return {};
}

const id = 'id';

function BasicData(props) {
  const {
    dataSource,
    pagination,
    removeBatchLoading,
    updateLoading,
    queryLoading,
  } = props;
  // #region use hook
  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
  const [selectedRows, setSelectedRows] = useState([]);
  const [reloadPagination, setReloadPagination] = useState();
  const [editActualValueModalVisible, setEditActualValueModalVisible] = useState(false);
  const [editRecord, setEditRecord] = useState({});
  const searchFormRef = useRef(null);
  const handleSearch = (pagination = {}) => {
    const {query} = props;
    const queryData = getFieldsValueByRef(searchFormRef);
    setReloadPagination(pagination);
    setSelectedRowKeys([]);
    setSelectedRows([]);
    return query({
      query: {...queryData, ...pagination},
    });
  };
  useEffect(() => {
    handleSearch();
  }, []);
  // #endregion
  const delBtnClick = () => {
    const {removeBatch} = props;
    removeBatch({records: selectedRows})
      .then(res => {
        if (res) {
          notification.success();
          reload();
        }
      })
  };
  const onRowSelectionChange = ({selectedRowKeys = [], selectedRows = []}) => {
    setSelectedRowKeys(selectedRowKeys);
    setSelectedRows(selectedRows)
  };
  const onRecordEdit = (record) => {
    setEditActualValueModalVisible(true);
    setEditRecord(record);
  };
  const onTableChange = (page, filter, sort) => {
    handleSearch({page, sort});
  };
  const reload = () => {
    handleSearch(reloadPagination);
  };
  const closeEditFormModal = () => {
    setEditActualValueModalVisible(false);
    setEditRecord({});
  };
  const onRecordActualValueEditOk = (record) => {
    const {update} = props;
    update({record: {...editRecord, ...record}, id: editRecord[id]}).then((res) => {
      if (res) {
        notification.success();
        closeEditFormModal();
        reload();
      }
    })
  };
  const onRecordActualValueEditCancel = () => {
    closeEditFormModal();
  };
  const languageMessage = getLanguageMessage();
  return (
    <>
      <Header>
        <Popconfirm
          title={languageMessage.common.message.confirm.remove}
          onConfirm={delBtnClick}
        >
          <Button
            disabled={selectedRows.length === 0}
            loading={removeBatchLoading}
            type="primary"
          >
            {languageMessage.common.btn.del}
          </Button>
        </Popconfirm>
      </Header>
      <Content>
        <SearchForm
          languageMessage={languageMessage}
          queryLoading={queryLoading}
          removeBatchLoading={removeBatchLoading}
          onSearch={handleSearch}
          ref={searchFormRef}
        />
        <DataTable
          onRowSelectionChange={onRowSelectionChange}
          onRecordActualValueEdit={onRecordEdit}
          onChange={onTableChange}
          dataSource={dataSource}
          pagination={pagination}
          languageMessage={languageMessage}
          selectedRowKeys={selectedRowKeys}
          queryLoading={queryLoading}
          removeBatchLoading={removeBatchLoading}
        />
        <ActualValueEditModal
          languageMessage={languageMessage}
          visible={editActualValueModalVisible}
          record={editRecord}
          onOk={onRecordActualValueEditOk}
          onCancel={onRecordActualValueEditCancel}
          updateLoading={updateLoading}
        />
      </Content>
    </>
  );
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(formatterCollections({code: ['hnlp.basicData']})(BasicData));


function mapStateToProps({nlpBasicData = {}, loading = {}}) {
  const {
    dataSource,
    pagination,
    enums,
  } = nlpBasicData;
  return {
    dataSource,
    pagination,
    enums,
    initLoading: loading.effects['nlpBasicData/init'],
    removeBatchLoading: loading.effects['nlpBasicData/removeBatch'],
    updateLoading: loading.effects['nlpBasicData/update'],
    queryLoading: loading.effects['nlpBasicData/query'],
  };
}

function mapDispatchToProps(dispatch) {
  return {
    init: (payload) => {
      return dispatch({
        type: 'nlpBasicData/init',
        payload,
      })
    },
    removeBatch: (payload) => {
      return dispatch({
        type: 'nlpBasicData/removeBatch',
        payload,
      });
    },
    update: (payload) => {
      return dispatch({
        type: 'nlpBasicData/update',
        payload,
      });
    },
    query: (payload) => {
      return dispatch({
        type: 'nlpBasicData/query',
        payload,
      });
    },
  };
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容

  • React是现在最流行的前端框架之一,它的轻量化,组件化,单向数据流等特性把前端引入了一个新的高度,现在它又引入的...
    老鼠AI大米_Java全栈阅读 5,780评论 0 26
  • 你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗?——拥有了hooks,你再也不需...
    水落斜阳阅读 82,329评论 11 100
  • 你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗?——拥有了hooks,你再也不需...
    米亚流年阅读 943评论 0 5
  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 8,454评论 1 33
  • 在学会使用React Hooks之前,可以先看一下相关原理学习React Hooks 前言 在 React 的世界...
    DC_er阅读 9,099评论 1 16