Cannot read property 'style' of undefined React Material UI - reactjs

I am trying to make a collapsible row inside a row. Basically I render a bunch of rows with pharmaceutical drugs, and I want someone to click on that row and it would show the description of that pharmaceutical drug.
I thought it was pretty straight forward but my code doesn't seem to work as I get the error I have described on my title.
Here's my code:
<TableContainer component={Paper} style={{overflow: "hidden"}}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell />
<TableCell><strong>Pharmaceutical Drug</strong></TableCell>
<TableCell align="right"><strong>Drug Class</strong></TableCell>
<TableCell align="right"><strong>Adult Dosage</strong></TableCell>
<TableCell align="right"><strong>Pediatric Dosage</strong></TableCell>
<TableCell align="right"><strong>Administration</strong></TableCell>
</TableRow>
</TableHead>
<TableBody>
{drugs.map((drug) => (
<Slide direction="up" in={drugs} mountOnEnter unmountOnExit>
<TableRow key={drug._id}>
<TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
<TableCell>{drug.name}</TableCell>
<TableCell align="right">{drug.class}</TableCell>
<TableCell align="right">{drug.suggestedDoseAdult}</TableCell>
<TableCell align="right">{drug.suggestedDosePediatric}</TableCell>
<TableCell align="right">{drug.administered}</TableCell>
</TableRow>
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
{drug.description}
</Typography>
</Box>
</Collapse>
</TableCell>
</TableRow>
</Slide>
))}
</TableBody>
</Table>
</TableContainer>
Here's the error:
TypeError: Cannot read property 'style' of undefined
(anonymous function)
node_modules/#material-ui/core/esm/Slide/Slide.js:214
211 | }, other), function (state, childProps) {
212 | return /*#__PURE__*/React.cloneElement(children, _extends({
213 | ref: handleRef,
> 214 | style: _extends({
| ^ 215 | visibility: state === 'exited' && !inProp ? 'hidden' : undefined
216 | }, style, children.props.style)
217 | }, childProps));

You'll need to import TableContainer from Material UI. Just add this import to the top of your component file and you should be all set.
import { TableContainer } from '#material-ui/core';

Related

Chip Component doesn't show up

const ResultsAccordion = ({projects, projectStatus}) =>
{
return (
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="panel1a-content" id="panel1a-header">
<Typography>{projectStatus}</Typography>
</AccordionSummary>
<AccordionDetails>
<TableContainer component={Paper} sx={{my:2 }}>
<Table>
<TableHead>
<TableRow style={{ width:"100%" }}>
<TableCell align="center">Team Name</TableCell>
<TableCell align="center">Project Link</TableCell>
<TableCell align="center">Team Members</TableCell>
</TableRow>
</TableHead>
<TableBody>
{
projects.map((value) =>
{
return (
<TableRow key={value.name}>
<TableCell align="center">
{value.name}
</TableCell>
<TableCell align="center">
<Link href={value.repo}>Project Repo</Link>
</TableCell>
<TableCell align="center">
<Stack direction="row" spacing={1} alignContent="center">
{
(value.members).map((item, key) =>
{
return (
<Chip key={key} component="a" href={`https://github.com/${item.github}`} clickable label={item.github} avatar={<Avatar alt={item.github} src={item.avatar}/> } />
);
})
}
</Stack>
</TableCell>
</TableRow>
);
})
}
</TableBody>
</Table>
</TableContainer>
</AccordionDetails>
</Accordion>
);
};
Chips are supposed to be returned in the Table Cell with Stack..
But there is no one.
I used the react Developers tools and there is no childrens in Stack.
The chips are rendered if i made any changes in the prop using ReactDevTools
I checked, the value.members array & it is also not empty.

Material UI, Warning <td> cannot appear as a child of <div>

I'm using React, typescript and Material UI. I've created a pretty common "Create user form" with basic inputs for username, name, email, ect. Added two buttons, "Edit" and "Delete." Everything seems to function properly, however, I cannot get this error message resolved.
Warning: validateDOMNesting(...): <td> cannot appear as a child of <div>.
Here's the table from a react component:
<TableContainer className={classes.scroll} component={Paper}>
<Table stickyHeader aria-label="table">
<TableHead>
<TableRow>
<TableCell>Username</TableCell>
<TableCell align="right">First name</TableCell>
<TableCell align="right">Last name</TableCell>
<TableCell align="right">Email</TableCell>
<TableCell align="right">Connect_username</TableCell>
<TableCell align="right">Role</TableCell>
<TableCell align="left">Edit</TableCell>
<TableCell align="left">Delete</TableCell>
</TableRow>
</TableHead>
<TableBody>
{(rowsPerPage > 0
? props?.items.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: props?.items
).map(item => (
<TableRow key={item.user_id}>
<TableCell component="th">{item.username}</TableCell>
<TableCell align="right">{item.first_name}</TableCell>
<TableCell align="right">{item.last_name}</TableCell>
<TableCell align="right">{item.email}</TableCell>
<TableCell align="right">{item.connect_username}</TableCell>
<TableCell align="right">{item.role?.map(r=>r.role).join(",")}</TableCell>
<TableCell>
<Button onClick={() => props.handleEdit(item)}>Edit</Button>
</TableCell>
<TableCell>
<Button onClick={() => props.handleConfirmDelete(item.user_id)}>Delete</Button>
</TableCell>
</TableRow>
))}
</TableBody>
<TablePagination
rowsPerPageOptions={[10, 25, { label: 'All', value: -1 }]}
count={props.items.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Table>
</TableContainer>
component={Paper} is likely causing this. Can you try removing it? If you want the table to appear on a Paper component, then try nesting TableContainer under Paper.
put TablePagination in the TableBody tag and wrap it in TableRow.
Had a similar issue and this fixed it.
Like this:
<TableBody>
{(rowsPerPage > 0
? props?.items.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: props?.items)
.map(item => (
<TableRow key={item.user_id}>
<TableCell component="th">{item.username}</TableCell>
<TableCell align="right">{item.first_name}</TableCell>
<TableCell align="right">{item.last_name}</TableCell>
<TableCell align="right">{item.email}</TableCell>
<TableCell align="right">{item.connect_username}</TableCell>
<TableCell align="right">{item.role?.map(r=>r.role).join(",")}</TableCell>
<TableCell>
<Button onClick={() => props.handleEdit(item)}>
Edit
</Button>
</TableCell>
<TableCell>
<Button onClick={() => props.handleConfirmDelete(item.user_id)}>
Delete
</Button>
</TableCell>
</TableRow>
<TableRow>
<TablePagination
rowsPerPageOptions={[10, 25, { label: 'All', value: -1 }]}
count={props.items.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</TableRow>
))}
</TableBody>
update: "#mui/material": "^5.10.9"
in my case this error was causing TablePagination and not Paper component.
working solution is wrapping pagination not only with row but also footer as follow
<TableContainer component={Paper}>
<Table>
<TableBody>
...
</TableBody>
<TableFooter>
<TableRow>
<TablePagination />
</TableRow>
</TableFooter>
</Table>
</TableContainer>
mui docs: https://mui.com/material-ui/react-table/#custom-pagination-actions

Warning: React has detected a change in the order of Hooks called by null

The function is called on form submission. at first, it is working as expected but when calling this function on form submit. I get this following error.index.js:1 Warning: React has detected a change in the order of Hooks called by null. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks:
Previous render Next render
useState useState
undefined useState
Here is the code sample :
function TablerowsAdd ( x,i,header,handleRemove, startEditing,editIdx,handleChange,stopEditing,handleRemoveField,fieldIdx,startEditingField,fieldheader) {
const [open, setOpen] = useState(false);
const currentlyEditing = editIdx === i;
return (
<React.Fragment key={`tr-${i}`}>
<TableRow key={`tr-${i}`}>
{header.map((y, k) => (
<TableCell key={`trc-${k}`}>
{currentlyEditing ? (
<TextField
name={y.prop}
onChange={e => handleChange(e, y.prop, i)}
value={x[y.prop]}
/>
) : (
x[y.prop]
)}
</TableCell>
))}
<TableCell>
{currentlyEditing ? (
<CheckIcon onClick={() => stopEditing()} />
) : (
<EditIcon onClick={() => startEditing(i)} />
)}
<DeleteIcon onClick={() => handleRemove(i)} />
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)} >
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
</TableRow>
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
Fields
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
{fieldheader.map((x, i) => (
<TableCell key={`thc-${i}`}>{x.name} </TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{x.fields.map((fieldRow,y) => (
<TableRow key={`tr-${y}`}>
<TableCell>{fieldRow.bitname}</TableCell>
<TableCell>{fieldRow.bitmask}</TableCell>
<TableCell >{fieldRow.bitvalue}</TableCell>
<TableCell >{fieldRow.maskname}</TableCell>
<TableCell > {fieldRow.doc} </TableCell>
<TableCell >
<DeleteIcon onClick={() => handleRemoveField(i,fieldRow.bitname,y)} /> </TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
); };
If call count of TablerowsAdd varies, the call count of useState varies too.
Try using a component: <TablerowsAdd/> instead of method call: TablerowsAdd(). This way useState is called exactly once per component

Change Table Row color based on condition in React

I want to change table row color based on condition .
My code :
<TableBody>
{
this.props.result.alpha.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row,i) =>(
<TableRow key={i} >
<TableCell component="th" scope="row" >
<Typography variant="h4"> {row.a} </Typography>
</TableCell>
<TableCell align="left" > <Typography variant="h4">{row.b}</Typography> </TableCell>
<TableCell align="left" > <Typography variant="h4"> {row.c} </Typography> </TableCell>
</TableRow>
))}
</TableBody>
Now i want to check if the value of key==null then color of row should be some color1 or else color2
i.e., Something like this.
if(row.c==null) then rowcolor= color1;
else rowcolor= color2;
How to do this in react ?
Nt: Your question is rather vague and need more clarification.
I suppose you want to set a class based on a condition, yeah?
You can use a tarnary operator to set a class name based on your condition.
First you need to create two classes. One for the positive condition and the other for the contrary.
Then do something like
<TableBody>
{
this.props.result.alpha.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row,i) =>(
<TableRow key={i} >
<TableCell component="th" scope="row" >
<Typography variant="h4"> {row.a} </Typography>
</TableCell>
<TableCell align="left" > <Typography variant="h4">{row.b}</Typography> </TableCell>
<TableCell align="left" > <Typography variant="h4" style={row.c === null ? blue : pink > {row.c} </Typography> </TableCell>
</TableRow>
))}
</TableBody>
const pink = {
backgroundColor: 'pink'
}
const blue ={
backgroundColor: 'blue'
}
Edit
In regards to the clarification made by the OP, I have changed from className to style.

How to fix the algorithm for table generation?

I have an algorithm for generating a table of two arrays.
data = [mail, cat, dog]
words = [{postman, mailbox, letter}, {kitty, kitten, koshak, kotyara}, {dog, friend}]
The number of "subarrays" in the words array is always equal to the number of elements in the data array.
The data array is the column headings, and the "subarrays" of words must be columns.
My generation algorithm works fine, but the "subarrays" in my implementation are obtained as rows, and as I said, I need to have columns.
<Paper style={{ maxWidth: 936, margin: "auto" }}>
<Table>
<TableHead>
<TableRow>
{data.map((TableRow, i) => (
<TableCell key={i} align="center">
{TableRow.split("_").join(" ")}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{this.state.array.map((user, i) => (
<TableRow key={i}>
{Object.values(user).map((v, j) => (
<TableCell key={j} align="center">
<IconButton>
<AddIcon/>
</IconButton>
{v}
<IconButton>
<RemoveIcon/>
</IconButton>
</TableCell>
))}
</TableRow>
))}
<TableRow>
<TableCell align="center">
<Button variant="contained"
color="primary"
style={{
background:
"linear-gradient(45deg, #00ACD3 30%, #00BE68 90%)"
}}
>Обучить
</Button>
</TableCell>
</TableRow>
</TableBody>
</Table>
</Paper>

Resources