const dataGenerator = () => ({ id: faker.string.uuid(), name: faker.person.fullName(), gender: faker.datatype.boolean() ? 'male' : 'female', score: { math: faker.number.int({ min: 30, max: 100 }), }, birthday: faker.date.between({ from: '1995-01-01', to: '2005-12-31' }), attachments: faker.number.int({ max: 5 }), description: faker.lorem.sentence(), email: faker.internet.email(), country: faker.location.country(), address: { street: faker.location.streetAddress(), city: faker.location.city(), zipCode: faker.location.zipCode(), }, }) const GenderContainer = styled.div` background-color: ${(props) => props.gender === 'male' ? 'lightblue' : 'pink'}; color: white; border-radius: 3px; width: 20px; height: 20px; font-size: 16px; font-weight: bold; line-height: 20px; text-align: center; ` const Gender = ({ gender }) => ( <GenderContainer gender={gender}> {gender === 'male' ? '♂' : '♀'} </GenderContainer> ) const Score = styled.span` color: ${(props) => (props.score >= 60 ? 'green' : 'red')}; ` const Attachment = styled.div` background-color: lightgray; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; color: gray; ` const defaultData = new Array(5000) .fill(0) .map(dataGenerator) .sort((a, b) => (a.name > b.name ? 1 : -1)) const defaultSort = { key: 'name', order: SortOrder.ASC } export default class App extends React.Component { state = { data: defaultData, sortBy: defaultSort, } columns = [ { key: 'name', title: 'Name', dataKey: 'name', width: 150, resizable: true, sortable: true, frozen: Column.FrozenDirection.LEFT, }, { key: 'score', title: 'Score', dataKey: 'score.math', width: 60, align: Column.Alignment.CENTER, sortable: false, }, { key: 'gender', title: '♂♀', dataKey: 'gender', cellRenderer: ({ cellData: gender }) => <Gender gender={gender} />, width: 60, align: Column.Alignment.CENTER, sortable: true, }, { key: 'birthday', title: 'Birthday', dataKey: 'birthday', dataGetter: ({ column, rowData }) => rowData[column.dataKey].toLocaleDateString(), width: 100, align: Column.Alignment.RIGHT, sortable: true, }, { key: 'attachments', title: 'Attachments', dataKey: 'attachments', width: 60, align: Column.Alignment.CENTER, headerRenderer: () => <Attachment>?</Attachment>, cellRenderer: ({ cellData }) => <Attachment>{cellData}</Attachment>, }, { key: 'description', title: 'Description', dataKey: 'description', width: 200, resizable: true, sortable: true, }, { key: 'email', title: 'Email', dataKey: 'email', width: 200, resizable: true, sortable: true, }, { key: 'country', title: 'Country', dataKey: 'country', width: 100, resizable: true, sortable: true, }, { key: 'address', title: 'Address', dataKey: 'address.street', width: 200, resizable: true, }, { key: 'action', width: 100, align: Column.Alignment.CENTER, frozen: Column.FrozenDirection.RIGHT, cellRenderer: ({ rowData }) => ( <button onClick={() => { this.setState({ data: this.state.data.filter((x) => x.id !== rowData.id), }) }} > Remove </button> ), }, ] onColumnSort = (sortBy) => { const order = sortBy.order === SortOrder.ASC ? 1 : -1 const data = [...this.state.data] data.sort((a, b) => (a[sortBy.key] > b[sortBy.key] ? order : -order)) this.setState({ sortBy, data, }) } render() { const { data, sortBy } = this.state return ( <> <button onClick={() => { this.setState({ toggle: !this.state.toggle, }) }} > Toggle columns </button> <button onClick={() => { this.setState({ data: [dataGenerator(), ...data], }) }} > Add item to top </button> <Table fixed columns={ !!this.state.toggle ? this.columns.slice(0, 4) : this.columns } estimatedRowHeight={40} data={data} sortBy={sortBy} onColumnSort={this.onColumnSort} /> </> ) } }