validateDOMNesting(...): <li> cannot appear as a descendant of <li> - reactjs

I'm getting the warning message validateDOMNesting(...): cannot descendant of li
in the console and it shows the error is on the treeview and the timeline I dont know where to fix the code, the below code is facing that warning is there any solution for this?
<Box>
<TreeView >
<Timeline key={comment.id}>
<TimelineItem>
<TimelineSeparator>
<Avatar {...stringAvatar(comment.username) } />{" "}
<TimelineConnector />
</TimelineSeparator>
<TimelineOppositeContent style={{maxWidth: "1px",paddingLeft: "0px",paddingRight: "0px", }}/>
<TimelineContent>
<Stack direction="row" spacing={1}>
<Typography variant="h6" sx={{fontSize:"15px" ,fontWeight:"bold"}}>
{comment.username.charAt(0).toUpperCase() + comment.username.slice(1)}
</Typography>
<Item variant="span" sx={{fontSize:"10px"}}> {createdAt}</Item>
</Stack>
<ReactMarkdown children={comment.body} rehypePlugins={[rehypeRaw]} />
<TreeItem
nodeId="1" label={
<TimelineContent>
{canReply && (<Chip label="Reply" onClick={() => setActiveComment({ id: comment.id, type: "replying", }) }
sx={{fontSize:"10px",mb:1}} size="small" icon={<ReplyIcon /> }/> )}
{isReplying && (
<CommentForm submitLabel="Reply" hasCancelButton handleSubmit={(text) => addComment(text, replyId)} handleCancel={() => { setActiveComment(null);}} />)}
</TimelineContent> } >
<TreeItem
nodeId="2"
label={
<Timeline>
{replies.length > 0 && (
<div>
{replies.map((reply) => (
<Comment
comment={reply}
key={reply.id}
setActiveComment={setActiveComment}
activeComment={activeComment}
addComment={addComment}
parentId={comment.id}
replies={[]}
currentUserId={currentUserId}
/>
))}
</div>
)}
</Timeline>}/>
</TreeItem>
</TimelineContent>
</TimelineItem>
</Timeline>
</TreeView>
</Box>

Related

React-admin: How to pass logged in user ID to API backend

I am using React-admin to make an application to manage articles and have many people logged in to write articles
I want to pass the USER_ID who is logged in to React-admin to CREATED_BY of API backend when posting a Article
Here is the code example for the add a Post function
export const PostCreate = (props) => {
return (
<Create {...props}>
<PostForm></PostForm>
</Create>)
};
const PostForm = (props ) => (
<FormWithRedirect
{...props}
render={(formProps) => (
// here starts the custom form layout
<form>
<Box p="1em">
<Box display="flex">
<Box flex={2} mr="1em">
<Typography variant="h6" gutterBottom>
Offer
</Typography>
<Box display="flex">
<TextInput source="title" fullWidth />
</Box>
<TextInput source="slug" fullWidth />
<ImageInput
source="pictures"
label="Related pictures"
accept="image/*"
fullWidth
>
<ImageField source="image" title="title" />
</ImageInput>
<TextInput multiline source="description" fullWidth />
<MarkdownInput source="content" fullWidth></MarkdownInput>
<Box mt="1em" />
<Typography variant="h6" gutterBottom>
Address
</Typography>
<Box display="flex">
<Box flex={1} mr="0.5em">
<BooleanInput label="Featured" source="featured" />
</Box>
<Box flex={1} mr="0.5em">
<BooleanInput label="Publish" source="published" />
</Box>
</Box>
</Box>
</Box>
</Box>
<Toolbar>
<Box display="flex" justifyContent="space-between" width="100%">
<SaveButton
saving={formProps.saving}
handleSubmitWithRedirect={formProps.handleSubmitWithRedirect}
redirect={
redirectEdit ? redirectEdit : `/posts/${formProps.record.id}`
}
/>
<DeleteButton
record={formProps.record}
redirect={`/posts/`}
/>
</Box>
</Toolbar>
</form>
)}
/>
)
I tried to get UserId from useGetIdentity
import { useGetIdentity } from "react-admin";
but don't know how to pass the value in
export const PostCreate = (props) => {
const { identity } = useGetIdentity();
return (
<Create {...props}>
<PostForm defaultValue={{ user_id: identity }}></PostForm>
</Create>)
};

Cannot read property map of undefined react

I'm trying to render a component that uses an array of filters to make a list. I pass the array as an argument to the function but it returns an error. The array is not null or undefined because it shows the itens if I log to the console.
Console.log returns:
Here is my code:
const List = (filtrosPorTipo) => {
let filtros = filtrosPorTipo[0]
let valoresDosFiltros = filtrosPorTipo[1]
let lista = (
<List>
{filtros.map((item, index) => {
return (
<>
<ListItem
button
onClick={() => setOpen({ [item]: !open[item] })}
key={item}
>
<ListItemText primary={item} />
{open[item] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open[item]} timeout='auto'>
<List component='div' disablePadding>
{valoresDosFiltros[index].map((filtro) => {
return (
<>
<ListItem key={filtro}>
<p>{`${filtro}\n`}</p>
<ListItemSecondaryAction>
<Checkbox
label={filtro}
key={filtro.toString()}
color='primary'
onChange={() => handleChecked(filtro)}
checked={checked[filtro]}
/>
</ListItemSecondaryAction>
</ListItem>
<Divider />
</>
)
})}
</List>
</Collapse>
</>
)
})}
</List>
)
return lista
}
Error:
Perhaps the component it's trying to render before "filtros" is assigned. It's a common and logical behavior in React.
Try adding a conditional before the .map() call:
{filtros ? filtros.map((item, index) => {
return (
<>
<ListItem
button
onClick={() => setOpen({ [item]: !open[item] })}
key={item}
>
<ListItemText primary={item} />
{open[item] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open[item]} timeout='auto'>
<List component='div' disablePadding>
{valoresDosFiltros[index].map((filtro) => {
return (
<>
<ListItem key={filtro}>
<p>{`${filtro}\n`}</p>
<ListItemSecondaryAction>
<Checkbox
label={filtro}
key={filtro.toString()}
color='primary'
onChange={() => handleChecked(filtro)}
checked={checked[filtro]}
/>
</ListItemSecondaryAction>
</ListItem>
<Divider />
</>
)
})}
</List>
</Collapse>
</>
)
}) : null}
You can map over the values when they are present like so. If you are not planning on displaying a Loading screen in the process of waiting for the data then this would work. Otherwise use a ternary operator like the other answer.
{filtros && filtros.map((item, index) => {
return (
<>
<ListItem
button
onClick={() => setOpen({ [item]: !open[item] })}
key={item}
>
<ListItemText primary={item} />
{open[item] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open[item]} timeout='auto'>
<List component='div' disablePadding>
{valoresDosFiltros[index].map((filtro) => {
return (
<>
<ListItem key={filtro}>
<p>{`${filtro}\n`}</p>
<ListItemSecondaryAction>
<Checkbox
label={filtro}
key={filtro.toString()}
color='primary'
onChange={() => handleChecked(filtro)}
checked={checked[filtro]}
/>
</ListItemSecondaryAction>
</ListItem>
<Divider />
</>
)
})}
</List>
</Collapse>
</>
)
})}
While rendering the component you have to check data in filtrosPorTipo. It has an array value or not. Like below:
const List = (filtrosPorTipo) => {
if (filtrosPorTipo && filtrosPorTipo.length > 0) {
let filtros = filtrosPorTipo[0]
let valoresDosFiltros = filtrosPorTipo[1]
let lista = (
<List>
{filtros.map((item, index) => {
return (
<>
<ListItem
button
onClick={() => setOpen({ [item]: !open[item] })}
key={item}
>
<ListItemText primary={item} />
{open[item] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open[item]} timeout='auto'>
<List component='div' disablePadding>
{valoresDosFiltros[index].map((filtro) => {
return (
<>
<ListItem key={filtro}>
<p>{`${filtro}\n`}</p>
<ListItemSecondaryAction>
<Checkbox
label={filtro}
key={filtro.toString()}
color='primary'
onChange={() => handleChecked(filtro)}
checked={checked[filtro]}
/>
</ListItemSecondaryAction>
</ListItem>
<Divider />
</>
)
})}
</List>
</Collapse>
</>
)
})}
</List>
)
return lista
}
return 'No data available!'
}

how to show the contents in one ui using reactjs

I'm new to framework, the no.of contents are getting overloaded. the problem is when we have multiple users then their name need to be displayed according to the content of the message, for that we need to give mapping at first, but the data is getting overloaded.
Can anyone help me in this query?
Here is the code:
<div>
{this.state.data.map(item => {
return (
<Card>
<CardHeader
avatar={<div>Sanjana (or) someone else</div>}
title={
<>
<InputBase
placeholder="Search Google Maps"
margin="normal"
/>
<IconButton type="submit" aria-label="search">
<SearchIcon />
</IconButton>
</>
}
/>
<Divider />
<CardContent className={classes.contentHeight} id="chatList">
<div>
<Message isSender content={item.message} />
<Message content={item.message} />
</div>
</CardContent>
<Divider />
<CardActions>
<Paper className={classes.contentPaper}>
<Input
margin="dense"
className={classes.input}
placeholder="Enter a Message"
disableUnderline
/>
</Paper>
</CardActions>
</Card>
);
})}
</div>
Can anyone help me in this? thanks in advance!
I think you may want to only map the data messages, not the chat container(s)
render() {
const { classes } = this.props;
return (
<div>
<Card>
<CardHeader
avatar={<div>Sanjana (or) someone else</div>}
title={
<>
<InputBase placeholder="Search Google Maps" margin="normal" />
<IconButton type="submit" aria-label="search">
<SearchIcon />
</IconButton>
</>
}
/>
<Divider />
<CardContent className={classes.contentHeight} id="chatList">
{this.state.data.map(item => {
return (
<div>
<Message isSender content={item.message} />
<Message content={item.message} />
</div>
);
})}
</CardContent>
<Divider />
<CardActions>
<Paper className={classes.contentPaper}>
<Input
margin="dense"
className={classes.input}
placeholder="Enter a Message"
disableUnderline
/>
</Paper>
</CardActions>
</Card>
</div>
);
}

Slide Material-UI cannot read property style of "undefined"

I have implemented Material-UI Slide in my project recently and wanted to ask if someone could explain to me why the code works when I write it this way:
{selectedItem && selectedItem.modal && selectedItem.modal.body ? (
selectedItem.modal.body.map((section, key) => (
<Section section={section} key={key} />
))
) : (
<Slide
direction={animate === 'stepIn' ? 'right' : 'left'}
in={animate === 'idle'}
>
<Grid container={true} spacing={3}>
{items.map((item, key) => (
<Grid item={true} xs={6} md={4} lg={3} key={key}>
<MaterialCard
key={key}
onClick={onCardClicked(item)}
className={classes.card}
>
<CardActionArea className={classes.cardArea}>
<CardMedia
image={item.image || undefined}
component="img"
/>
<CardContent className={classes.cardContent}>
<Typography
component="p"
className={classes.cardContentTypographyHeader}
>
<Hyphenated language={de}>{item.label}</Hyphenated>
</Typography>
{item.description ? (
<Typography
component="p"
className={classes.cardContentTypography}
>
<Hyphenated language={de}>
{item.description}
</Hyphenated>
</Typography>
) : null}
</CardContent>
</CardActionArea>
{selectedItem && selectedItem.id === item.id ? (
<>
<div className={classes.cardSelectedOverlay} />
<Done className={classes.cardSelectedOverlayIcon} />
</>
) : null}
</MaterialCard>
</Grid>
))}
</Grid>
</Slide>
But fails to compile when I move the section.map inside the slide. I want to animate the section coming in aswell.
<Slide
direction={animate === 'stepIn' ? 'right' : 'left'}
in={animate === 'idle'}
>
{selectedItem && selectedItem.modal && selectedItem.modal.body ? (
selectedItem.modal.body.map((section, key) => (
<Section section={section} key={key} />
))
) : (
<Grid container={true} spacing={3}>
{items.map((item, key) => (
<Grid item={true} xs={6} md={4} lg={3} key={key}>
<MaterialCard
key={key}
onClick={onCardClicked(item)}
className={classes.card}
>
<CardActionArea className={classes.cardArea}>
<CardMedia
image={item.image || undefined}
component="img"
/>
<CardContent className={classes.cardContent}>
<Typography
component="p"
className={classes.cardContentTypographyHeader}
>
<Hyphenated language={de}>{item.label}</Hyphenated>
</Typography>
{item.description ? (
<Typography
component="p"
className={classes.cardContentTypography}
>
<Hyphenated language={de}>
{item.description}
</Hyphenated>
</Typography>
) : null}
</CardContent>
</CardActionArea>
{selectedItem && selectedItem.id === item.id ? (
<>
<div className={classes.cardSelectedOverlay} />
<Done className={classes.cardSelectedOverlayIcon} />
</>
) : null}
</MaterialCard>
</Grid>
))}
</Grid>
)}
</Slide>
The code works for every card, except the ones with a modal inside them. A modal contains e.g. text, textinput. When I click on a card with a modal inside of it i get this error:
Thanks for your help!
In the documentation for Slide's children prop you can find:
A single child content element.
⚠️ Needs to be able to hold a ref.
Slide uses React.cloneElement to add a ref and props to the single child. If there are multiple children or if children is an array (even if the array contains only one child), then Slide will get the error you encountered because children.props is not defined and it is trying to reference children.props.style.
Below is a little example to just help better understand the cause of the error:
import React from "react";
import ReactDOM from "react-dom";
const MockSlide = ({ children }) => {
if (children.props) {
return (
<div>
{children}
children.props is defined
</div>
);
}
return (
<div>
{children}
children.props is not defined
</div>
);
};
const sectionArray = [
"An array also causes problems (even if only one element)"
];
function App() {
return (
<div className="App">
<MockSlide>
<div>Single child works fine</div>
</MockSlide>
<br />
<br />
<MockSlide>
<div>Multiple children</div>
<div>causes problems with Slide</div>
</MockSlide>
<br />
<br />
<MockSlide>
{sectionArray.map(section => {
return <div>{section}</div>;
})}
</MockSlide>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
One potential solution is to wrap everything inside the Slide in a single <div> element.

How to fix shadow for menu material-ui

When I use a few icon menus than box-shadow looks very dark. How to fix that?
1:
Codesandbox example https://codesandbox.io/embed/flamboyant-tdd-r83u1
<div>
{items.map((item, index) => {
return (
<Fragment key={index}>
<IconButton
aria-owns={open ? "long-menu" : undefined}
onClick={this.handleClick}
>
<MoreVertIcon />
</IconButton>
<Menu anchorEl={anchorEl} open={open} onClose={this.handleClose}>
{options.map(option => (
<MenuItem key={option} onClick={this.handleClose}>
{option}
</MenuItem>
))}
</Menu>
</Fragment>
);
})}
</div>
Because, actually you are triggering multiple menus with the same flag at the same time. So shadow is dark because there are multiple menus one after the other.
Below code should fix this, You don't have to render Menu in items loop
render() {
const items = [...Array(10).keys()];
const { anchorEl } = this.state;
const open = Boolean(anchorEl);
return (
<div>
{items.map((item, index) => {
return (
<Fragment key={index}>
<IconButton
aria-owns={open ? "long-menu" : undefined}
onClick={this.handleClick}
>
<MoreVertIcon />
</IconButton>
</Fragment>
);
})}
<Menu anchorEl={anchorEl} open={open} onClose={this.handleClose}>
{options.map(option => (
<MenuItem key={option} onClick={this.handleClose}>
{option}
</MenuItem>
))}
</Menu>
</div>
);
}

Resources