React Hooks 使用
使用感想
- 更加利于阅读的代码
- 代码量更少
- 使用更方便
- 由原代码修改为 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,
});
},
};
}