import React, { useImperativeHandle, useRef, useEffect, useCallback, useState, useMemo } from 'react' const itemSize = 40; const Table = React.forwardRef((props, ref) => { const {columns = [], mainKey = 'id', autoNext = true, pageFinished, dataSource} = props; const sizeRef = useRef(); const tableRef = useRef(); const [pageSize, setPageSize] = useState(0); const [page, setPage] = useState(1); const [data, setData] = useState([]) const totalPage = useMemo( () => Math.ceil(data.length / pageSize), [data, pageSize] ); const currentData = useMemo( () => data.slice(pageSize * (page - 1), pageSize * page), [data, pageSize, page] ) const tableSetting = useCallback(() => { let { offsetHeight, scrollHeight, offsetWidth, scrollWidth } = tableRef.current; let pageSize = Math.floor(offsetHeight / itemSize) - 1; setPageSize(pageSize); }, []) const nextPage = useCallback(() => { if(page + 1 > totalPage){ if(autoNext){ setPage(1); }else{ pageFinished && pageFinished(); } }else{ setPage(page + 1); } }, [totalPage, page]) useEffect(() => { let innerWindow = sizeRef.current.contentDocument.defaultView; innerWindow.addEventListener("resize", tableSetting); tableSetting(); return () => { innerWindow.removeEventListener("resize", tableSetting); } }, [tableSetting]) useEffect(() => { if (dataSource) { setData(dataSource); setPage(1); } }, [dataSource]); useImperativeHandle(ref, () => ({ nextPage, setData: data => { setData(data); setPage(1); }, addData: addData => { setData(data.concat(...addData)) }, updateData: updateData => { setData(data.map(item => { let mainValue = item[mainKey]; let update = updateData.find(i => i[mainKey] === mainValue); if(update) item = update; return item; })) }, deleteData: deleteData => { setData(data.filter(item => { let mainValue = item[mainKey]; return !deleteData.find(i => i[mainKey] === mainValue); })) }, }), [data, nextPage, mainKey]) return (
{columns.map(({title, width}) => { let thProps = {key: title}; if(width !== undefined) thProps.style = {width: width + 'px'} return })} {currentData.map((item, index) => ( {columns.map(config => { let {title,code, render} = config; if(render) return ; return })} ))}
{title}
{render(item[code], config, item)}{item[code]}
); }) export default Table;