Skip to content

Instantly share code, notes, and snippets.

@nmoinvaz

nmoinvaz/cursortable.js

Last active Jun 26, 2021
Embed
What would you like to do?
Antd Cursor Paginated Table Component
import React, { useEffect, useState } from "react";
import { Table, Button, Space, Row, Col } from "antd";
import { LeftOutlined, RightOutlined } from "@ant-design/icons";
const CursorPagination = ({ lastEvaluatedKey, onChange, size }) => {
/* Use stack to keep track of which evaluated keys have been previously seen */
const [ prevEvaluatedKeys, setPrevEvaluatedKeys ] = useState([]);
/* Keep track of the current evaluated key */
const [ currentEvaluatedKey, setCurrentEvaluatedKey ] = useState(null);
/* Button style changes based on size */
const [ buttonStyle, setButtonStyle ] = useState({});
const popEvaluatedKey = () => {
const prevEvaluatedKey = prevEvaluatedKeys.pop();
setCurrentEvaluatedKey(prevEvaluatedKey);
return prevEvaluatedKey;
};
const pushEvaluatedKey = (evaluatedKey) => {
setPrevEvaluatedKeys([...prevEvaluatedKeys, currentEvaluatedKey]);
setCurrentEvaluatedKey(evaluatedKey);
return evaluatedKey;
};
const extra = { action: "paginate" };
useEffect(() => {
switch (size) {
case "small":
setButtonStyle({paddingLeft: "4px", paddingRight: "4px", borderColor: "transparent"});
break;
case "default":
default:
setButtonStyle({paddingLeft: "7px", paddingRight: "7px"});
break;
}
}, [size]);
/* Display forward and back buttons */
return (
<Space direction="horizontal">
<Button tabIndex={-1} size={size}
disabled={!prevEvaluatedKeys.length && prevEvaluatedKeys.length <= 1}
style={buttonStyle}
onClick={() => onChange(popEvaluatedKey(), undefined, undefined, extra)}>
<LeftOutlined/>
</Button>
<Button tabIndex={-1} size={size}
disabled={!lastEvaluatedKey}
style={buttonStyle}
onClick={() => onChange(pushEvaluatedKey(lastEvaluatedKey), undefined, undefined, extra)}>
<RightOutlined/>
</Button>
</Space>
);
};
export default function CursorTable(props) {
const { children, pagination, dataSource, onChange } = props;
const { position = "bottomRight", size = "default" } = pagination || {};
const [ lastEvaluatedKey, setLastEvaluatedKey ] = useState(null);
const [ verticalPosition, alignmentPosition ] =
position.match(/[A-Z]?[a-z]+/g);
const justifyPosition = {
left: "start",
center: "center",
right: "end"
}[alignmentPosition.toLowerCase()];
useEffect(() => {
/* Get last evaluated key from last item in data source */
const [ lastDataItem ] = (dataSource || []).slice(-1);
setLastEvaluatedKey(lastDataItem?.lastEvaluatedKey);
}, [dataSource]);
return (
<Space direction="vertical" style={{width: "100%"}}>
{verticalPosition === "top" &&
<Row justify={justifyPosition}>
<Col>
<CursorPagination
lastEvaluatedKey={lastEvaluatedKey}
onChange={onChange}
size={size}/>
</Col>
</Row>}
<Table {...props} pagination={{position: ["none", "none"]}}>
{children}
</Table>
{verticalPosition === "bottom" &&
<Row justify={justifyPosition}>
<Col>
<CursorPagination
lastEvaluatedKey={lastEvaluatedKey}
onChange={onChange}
size={size}/>
</Col>
</Row>}
</Space>
);
}
@silicakes

This comment has been minimized.

Copy link

@silicakes silicakes commented May 14, 2021

You're not using evaluatedKey in your pushEvaluatedKey/popEvaluatedKey, is that intentional?

@nmoinvaz

This comment has been minimized.

Copy link
Owner Author

@nmoinvaz nmoinvaz commented May 14, 2021

Good catch I have fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment