[JSDC 2017] 趨勢科技 - 誰是效能王
Demo: https://trendmicro-frontend.github.io/react-table-performance-tuning/
活動說明
- 針對題目範例做效能優化,重繪時間越短則名次越佳,現場工作人員驗證後會將結果即時更新在英雄榜和臉書
- 獎金和贈品:
- 第一名:獎金 5000 元
- 第二名:獎金 3000 元
- 第三名:獎金 2000 元
- 第四~十名:趨勢科技專屬 T-Ball 悠遊卡
- 未得獎參賽者每人皆可得趨勢好禮一份
- 第一名:獎金 5000 元
- 活動期間:2017/11/4 9:00 AM 到 2017/11/5 12:00 PM (由工作人員開始計算名次)
- 名次公布:第二天下午二點半(14:55休息時間進行頒獎)
活動流程
-
參賽者根據海報上的資訊取得此專案網址,並 Fork 回參賽者的 GitHub 帳號下作答
-
參賽者將修改過後的結果 push 回 Fork 的專案中,並且用 GitHub Page 建立 Demo Site
-
參賽者將 Fork 的專案網址連同 Demo Site 提供給趨勢科技攤位的工作人員,並留下參賽者的姓名及聯絡方式
-
驗證方式:
- 用現場工作人員準備的電腦打開參賽者的 GitHub 專案和 Demo Site
- 檢查 Table 裡的資料數量(5000筆)是否正確
- 檢查 Table 內容能否正確呈現
- 按下 [Toggle All] 取得秒數(此步驟執行五次取最佳值)
- 用現場工作人員準備的電腦打開參賽者的 GitHub 專案和 Demo Site
Requirement
There are 5000 records in the table. Your goal is to improve the render time by resolving the performance issue when toggling all the checkboxes.
Setup
-
Run
npm run dev
to run webpack-dev-server for development. -
Run
npm run prepublish
to build production code and push the changes to your forked repository. -
Go to Settings > GitHub Pages and use the
/docs
folder for GitHub Pages. -
Copy the URL of your published site and update the link in README.md or in the repository's website.
Examples
examples/Selectable.jsx
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import Table from '../src';
import Checkbox from './Checkbox';
import styles from './index.styl';
class Selectable extends PureComponent {
static propTypes = {
data: PropTypes.array,
onUpdateStart: PropTypes.func,
onUpdateEnd: PropTypes.func
};
state = {
data: this.props.data
};
node = {
checkbox: null
};
toggleAll = () => {
if (!this.node.checkbox) {
return;
}
const node = ReactDOM.findDOMNode(this.node.checkbox);
const checked = node.checked;
this.setState(state => ({
data: state.data.map(item => ({
...item,
checked: !checked
}))
}));
};
renderHeaderCheckbox = () => {
const dataLength = this.state.data.length;
const selectedLength = this.state.data.filter(data => !!data.checked).length;
const checked = selectedLength > 0;
const indeterminate = selectedLength > 0 && selectedLength < dataLength;
return (
<Checkbox
ref={node => {
this.node.checkbox = node;
}}
checked={checked}
indeterminate={indeterminate}
onChange={event => {
const checkbox = event.target;
const checked = !!checkbox.checked;
this.setState(state => ({
data: state.data.map(item => ({
...item,
checked: checked
}))
}));
}}
/>
);
};
getRowClassName = (record, key) => {
const checked = record.checked;
if (checked) {
return styles.active;
} else {
return null;
}
};
onRowClick = (record, index, e) => {
const checked = record.checked;
this.setState(state => ({
data: state.data.map(item => {
if (record.id === item.id) {
return {
...item,
checked: !checked
};
}
return item;
})
}));
};
columns = [
{
title: this.renderHeaderCheckbox,
dataKey: 'checked',
render: (value, row) => (
<Checkbox
id={row.id}
className="input-checkbox"
checked={row.checked}
/>
),
width: 38
},
{
title: '#',
dataKey: 'id'
},
{
title: 'Event Type',
dataKey: 'eventType'
},
{
title: 'Affected Devices',
dataIndex: 'affectedDevices'
},
{
title: 'Detections',
dataIndex: 'detections'
}
];
componentWillUpdate() {
this.props.onUpdateStart();
}
componentDidUpdate() {
this.props.onUpdateEnd();
}
render() {
return (
<Table
justified={false}
rowKey="id"
columns={this.columns}
data={this.state.data}
rowClassName={this.getRowClassName}
onRowClick={this.onRowClick}
maxHeight={400}
/>
);
}
}
export default Selectable;
Table API
Properties
Table
Name | Type | Default | Description |
---|---|---|---|
bordered | Boolean | true | Specify whether the table should be bordered. |
justified | Boolean | true | Specify whether to keep table columns equal width. |
columns | Object[] | [] | The columns config of table, see Column below for details. |
data | Object[] | [] | Data record array to be rendered. |
emptyText | Function | () => { return 'No Data'; } | Display text when data is empty. |
expandedRowKeys | String[] | Current expanded rows keys. | |
expandedRowRender | Function(record, key) | Expanded content render function. | |
footer | React Node or Function(): React Node | Table footer render function. | |
hoverable | Boolean | true | Whether use row hover style. |
loading | Boolean | false | Whether table is loading. |
maxHeight | Number | Table maximum height. | |
onRowClick | Function(record, key) | Handle rowClick action. | |
showHeader | Boolean | true | Whether table head is shown. |
sortable | Boolean | false | Whether table head is sortable. |
title | React Node or Function(): React Node | Table title render function. | |
useFixedHeader | Boolean | false | Whether table head is fixed. |
rowClassName | Function(record, key):string | Get row's className. | |
rowKey | string or Function(record):string | 'key' | If rowKey is string, record[rowKey] will be used as key. If rowKey is function, the return value of rowKey(record) will be use as key. |
Column
Name | Type | Default | Description |
---|---|---|---|
key | String | key of this column is for sortable attribute. | |
className | String | className of this column. | |
style | String | style of this column. | |
headerClassName | String | className to assign to the column header. | |
headerStyle | String | style to assign to the column header. | |
cellClassName | String | className to assign to each cell in the column. | |
cellStyle | String | style to assign to each cell in the column. | |
onClick | Function(event) | onClick event handler for header cell. | |
title | React Node or Function(): React Node | Title of this column. | |
dataIndex | String | Display field of the data record. | |
dataKey | String | dataKey is an alias for dataIndex. | |
width | String or Number | Width of the specific proportion calculation according to the width of the columns. | |
fixed | Boolean | false | This column will be fixed at left side when table scroll horizontally. |
render | Function(value, row) | The render function of cell, has two params: the text of this cell, the record of this row, it's return a react node. |
License
MIT