'Chrome Extension with React + MaterialUI - Table did not get filled with data
I am currently building a browser extension. I am struggling with showing data in a table (which is created with MatarialUI and React). I don't get any errors. Everything else gets rendered perfectly, and the console output displays that the data is present and in the correct format. So, I do not know where my mistake is. Maybe someone sees it and can help me.
options.tsx (produces the option.js and option.html for the browser extension)
import React from 'react';
import ReactDOM from 'react-dom';
import { Box, Card, CardContent, Typography, Grid } from '@material-ui/core';
import 'fontsource-roboto';
import './options.css';
import WhitelistTable from './whitelist';
const Options: React.FC<{}> = () => {
return (
<>
<Box mx={'4px'} my={'16px'}>
<Card>
<CardContent>
<Grid
container
direction="column"
alignItems="center"
justifyContent="center"
>
<Grid item>
<Typography variant="h3">SOMENAME</Typography>
</Grid>
<Grid item>
<img id="option-logo" src="images/shield_green.png" />
</Grid>
</Grid>
</CardContent>
</Card>
</Box>
<Box mx={'4px'} my={'16px'}>
<Card>
<CardContent>
<WhitelistTable />
</CardContent>
</Card>
</Box>
</>
);
};
const root = document.createElement('div');
document.body.appendChild(root);
ReactDOM.render(<Options />, root);
whitelist.tsx (generates the Table)
import * as React from 'react';
import { WLstruc, getStoredID, getStoredWhitelist } from '../utils/storage';
import { alpha, useTheme } from '@mui/material/styles';
import Box from '@mui/material/Box';
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 TableFooter from '@mui/material/TableFooter';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import TableSortLabel from '@mui/material/TableSortLabel';
import MaterialTable from 'material-table';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Paper from '@mui/material/Paper';
import Checkbox from '@mui/material/Checkbox';
import IconButton from '@mui/material/IconButton';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import FirstPageIcon from '@mui/icons-material/FirstPage';
import LastPageIcon from '@mui/icons-material/LastPage';
import Tooltip from '@mui/material/Tooltip';
import FormControlLabel from '@mui/material/FormControlLabel';
import Switch from '@mui/material/Switch';
import DeleteIcon from '@mui/icons-material/Delete';
import FilterListIcon from '@mui/icons-material/FilterList';
import { visuallyHidden } from '@mui/utils';
export default function Whitelist() {
const [whitelist, getWhitelist] = React.useState<WLstruc | null>(null);
React.useEffect(() => {
getStoredWhitelist().then((whitelist) => getWhitelist(whitelist));
}, []);
if (!whitelist) {
return null;
}
console.log(whitelist);
return (
<>
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>URL</TableCell>
<TableCell>Date added</TableCell>
<TableCell>Expire</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow key={whitelist.id}>
<TableCell>{whitelist.url}</TableCell>
<TableCell>{whitelist.date_added}</TableCell>
<TableCell>{whitelist.expire}</TableCell>
<TableCell>
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</TableCell>
</TableRow>
</TableBody>
<TableFooter>
<TableRow>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
</>
);
}
storage.ts (to get the data from the Chrome API)
export interface WLstruc {
id: number;
url: string;
date_added: string;
expire: boolean;
}
export function getStoredWhitelist(): Promise<WLstruc> {
return new Promise((resolve) => {
chrome.storage.local.get({ whitelist: [] }, (res) => {
resolve(res.whitelist);
});
});
}
console output
(4) [{…}, {…}, {…}, {…}]
0: {date_added: '20220313', expire: false, id: 1, url: 'https://google.com/'}
1: {date_added: '20220313', expire: false, id: 2, url: 'https://apple.com/'}
2: {date_added: '20220313', expire: false, id: 3, url: 'https://microsoft.com/'}
3: {date_added: '20220313', expire: false, id: 4, url: 'https://cloudflare.com/'}
length: 4
[[Prototype]]: Array(0)

Solution 1:[1]
Thank you @wOxxOm for your help. Now it works. But, the solution is weird and a bit different as you recommended.
I changed
const [whitelist, getWhitelist] = React.useState<WLstruc | null>(null);
to
const [whitelist, getWhitelist] = React.useState<any | null>(null);
and I modified
export function getStoredWhitelist(): Promise<WLstruc> {
return new Promise((resolve) => {
chrome.storage.local.get({ whitelist: [] }, (res) => {
resolve(res.whitelist);
});
});
}
to
export function getStoredWhitelist(): Promise<any> {
return new Promise((resolve) => {
chrome.storage.local.get({ whitelist: [] }, (res) => {
resolve(res.whitelist);
});
});
}
And finally, I loop with map through the array
{whitelist.map((row, index) => {
return (
<TableRow id={row.id}>
<TableCell>{row.url}</TableCell>
<TableCell>{row.date_added}</TableCell>
<TableCell>{row.expire}</TableCell>
<TableCell>
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</TableCell>
</TableRow>
);
})}
As recommended to remove the line
if (!whitelist) { return null; }
and/or changing the Hook to const [whitelist, getWhitelist] = React.useState<any>(); the program crashes and I get an error ("Uncaught TypeError: Cannot read properties of undefined (reading 'whitelist')"). When I keep it, everything works fine. Now my storage is shown in the table:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shiro |
