# React Table with fix Scrollbar
:::spoiler <實作 TableContainerFixScrollbar compenment> {state="open"}
```javascripr=
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@mui/styles';
import TableContainer from '@mui/material/TableContainer';
const useStyles = makeStyles(() => ({
scrollbarWrapper: {
position: 'sticky',
bottom: 0,
left: 0,
right: 0,
height: '20px',
overflowX: 'auto',
overflowY: 'hidden',
zIndex: 1000,
background: 'white',
borderTop: '1px solid rgba(224, 224, 224, 1)',
'&::-webkit-scrollbar': {
height: '12px',
},
'&::-webkit-scrollbar-track': {
background: '#f1f1f1',
},
'&::-webkit-scrollbar-thumb': {
background: '#888',
borderRadius: '6px',
},
'&::-webkit-scrollbar-thumb:hover': {
background: '#555',
},
},
scrollbarContent: {
height: '1px',
},
tableContainer: {
'&::-webkit-scrollbar': {
display: 'none', // hide scrollbar
},
scrollbarWidth: 'none', // Firefox hide scrollbar
msOverflowStyle: 'none', // IE/Edge hide scrollbar
},
}));
const TableContainerFixScrollbar = ({ children, data }) => {
const classes = useStyles();
const tableContainerRef = React.useRef(null);
const scrollbarRef = React.useRef(null);
React.useEffect(() => {
const tableContainer = tableContainerRef.current;
const scrollbar = scrollbarRef.current;
if (!tableContainer || !scrollbar) return;
const handleTableScroll = () => {
scrollbar.scrollLeft = tableContainer.scrollLeft;
};
const handleScrollbarScroll = () => {
tableContainer.scrollLeft = scrollbar.scrollLeft;
};
tableContainer.addEventListener('scroll', handleTableScroll);
scrollbar.addEventListener('scroll', handleScrollbarScroll);
// set scrollbar width same with table
const updateScrollbarWidth = () => {
const table = tableContainer.querySelector('table');
if (table && scrollbar.firstChild) {
scrollbar.firstChild.style.width = `${table.offsetWidth}px`;
}
};
updateScrollbarWidth();
return () => {
tableContainer.removeEventListener('scroll', handleTableScroll);
scrollbar.removeEventListener('scroll', handleScrollbarScroll);
};
}, [data]);
return (
<>
<TableContainer className={classes.tableContainer} ref={tableContainerRef}>
{children}
</TableContainer>
<div className={classes.scrollbarWrapper} ref={scrollbarRef}>
<div className={classes.scrollbarContent}></div>
</div>
</>
);
};
TableContainerFixScrollbar.propTypes = {
children: PropTypes.node.isRequired,
data: PropTypes.array
};
export default TableContainerFixScrollbar;
```
:::
:::spoiler <使用 TableContainerFixScrollbar compenment>
```javascript
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
function createData(
name: string,
calories: number,
fat: number,
carbs: number,
protein: number,
) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Gingerbread', 356, 16.0, 49, 3.9),
];
export default function BasicTable() {
return (
<TableContainerFixScrollbar data={rows}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow
key={row.name}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">{row.calories}</TableCell>
<TableCell align="right">{row.fat}</TableCell>
<TableCell align="right">{row.carbs}</TableCell>
<TableCell align="right">{row.protein}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
```
:::
要讓 Scrollbar 可以固定顯示在螢幕畫面下方,須將 `position 設為 'sticky'`,因此需用一個新的 div 模仿 scrollbar 的功能,跟原來的 table 切開 (line 87~89、 css scrollbarWrapper)
原來 table 的 scroball 則需隱藏 (css tableContainer)
Scrollbar 的寬度會因資料不同而變動,所以當有新資料傳入時,透過 `React.useEffect` 重新計算