在ReactJ中映射时,如何用OnClick在列表中的单个项目?
我的React组件从我的Firestore DB返回数据,并将其在材料-UI卡上映射。但是,当我按ExpandMoreicon时,它会打开每张卡。我只想单独打开每张卡。我知道该解决方案与扩展的Usestate功能有关。设定。
我试图修复此错误,但我似乎无法使其起作用。任何帮助将不胜感激。
export const NFTprojects = () => {
const [expanded, setExpanded] = useState(false);
const handleExpandClick = (id) => {
setExpanded(!expanded)
};
const [projects, setProjects] = useState([]);
const ref = firebase.firestore().collection("NFTprojects");
function getProjects() {
ref.onSnapshot((querySnapshot) => {
const items = []; //initiliaze empty array
querySnapshot.forEach((doc) => {
items.push(doc.data());
});
setProjects(items);
});
}
useEffect(() => {
getProjects();
}, []);
return (
<div>
<Grid container spacing={4} direction="row" justifyContent="flex-start" alignItems="flex-start">
{projects.map((project) => (
<Grid item xs={4}>
<Card sx={{ maxWidth: 400, borderRadius: 3, mb: 5 }}>
<CardMedia
component="img"
height="140"
image={project.imageUrl}
alt={project.projectName}
/>
<CardContent>
<Typography gutterBottom variant="h5" sx={{ fontWeight: 'bold' }}>
{project.projectName}
</Typography>
<Typography variant="h6" gutterBottom component="div" fontWeight="bold">
{project.jobPosition}
</Typography>
<Typography variant="body2" color="text.secondary" style={{ fontFamily: 'Merriweather' }}>
{project.projectDesc}
</Typography>
</CardContent>
<CardActions disableSpacing>
<Tooltip title="Website">
<IconButton aria-label="secondary marketplace" href={project.websiteLink} target="_blank">
<WebsiteIcon />
</IconButton>
</Tooltip>
<Tooltip title="Twitter">
<IconButton aria-label="twitter" href={project.twitterLink} target="_blank">
<TwitterIcon />
</IconButton>
</Tooltip>
<Tooltip title="Secondary">
<IconButton aria-label="Secondary market link" href={project.secondaryMarket} target="_blank">
<ShoppingCartIcon />
</IconButton>
</Tooltip>
<Tooltip title="Discord">
<IconButton aria-label="discord" href={project.discordLink} target="_blank">
<SvgIcon component={DiscordIcon} viewBox="0 0 600 476.6" />
</IconButton>
</Tooltip>
<Button size="small" variant="contained" sx={{ ml: 15, backgroundColor: 'black' }}>Apply</Button>
<ExpandMore
expand={expanded}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</ExpandMore>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Typography variant="h6" sx={{ fontWeight: 'bold' }} style={{ fontFamily: 'Merriweather' }}>Job Description:</Typography>
<Typography paragraph>
{project.jobDesc}
</Typography>
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>Prerequisites</Typography>
<Typography paragraph>
{project.jobPrereq}
</Typography>
</CardContent>
</Collapse>
</Card>
</Grid>
))}
</Grid>
</div >
);
}
My react component returns data from my Firestore DB and maps the data it on Material-UI cards. However, when I press the ExpandMoreIcon, it opens EVERY card. I just want to open each card individually. I know the solution has to do with useState function for expanded & setExpanded.
I've tried to fix this bug but I cant seem to make it work. Any help would be greatly appreciated.
export const NFTprojects = () => {
const [expanded, setExpanded] = useState(false);
const handleExpandClick = (id) => {
setExpanded(!expanded)
};
const [projects, setProjects] = useState([]);
const ref = firebase.firestore().collection("NFTprojects");
function getProjects() {
ref.onSnapshot((querySnapshot) => {
const items = []; //initiliaze empty array
querySnapshot.forEach((doc) => {
items.push(doc.data());
});
setProjects(items);
});
}
useEffect(() => {
getProjects();
}, []);
return (
<div>
<Grid container spacing={4} direction="row" justifyContent="flex-start" alignItems="flex-start">
{projects.map((project) => (
<Grid item xs={4}>
<Card sx={{ maxWidth: 400, borderRadius: 3, mb: 5 }}>
<CardMedia
component="img"
height="140"
image={project.imageUrl}
alt={project.projectName}
/>
<CardContent>
<Typography gutterBottom variant="h5" sx={{ fontWeight: 'bold' }}>
{project.projectName}
</Typography>
<Typography variant="h6" gutterBottom component="div" fontWeight="bold">
{project.jobPosition}
</Typography>
<Typography variant="body2" color="text.secondary" style={{ fontFamily: 'Merriweather' }}>
{project.projectDesc}
</Typography>
</CardContent>
<CardActions disableSpacing>
<Tooltip title="Website">
<IconButton aria-label="secondary marketplace" href={project.websiteLink} target="_blank">
<WebsiteIcon />
</IconButton>
</Tooltip>
<Tooltip title="Twitter">
<IconButton aria-label="twitter" href={project.twitterLink} target="_blank">
<TwitterIcon />
</IconButton>
</Tooltip>
<Tooltip title="Secondary">
<IconButton aria-label="Secondary market link" href={project.secondaryMarket} target="_blank">
<ShoppingCartIcon />
</IconButton>
</Tooltip>
<Tooltip title="Discord">
<IconButton aria-label="discord" href={project.discordLink} target="_blank">
<SvgIcon component={DiscordIcon} viewBox="0 0 600 476.6" />
</IconButton>
</Tooltip>
<Button size="small" variant="contained" sx={{ ml: 15, backgroundColor: 'black' }}>Apply</Button>
<ExpandMore
expand={expanded}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</ExpandMore>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Typography variant="h6" sx={{ fontWeight: 'bold' }} style={{ fontFamily: 'Merriweather' }}>Job Description:</Typography>
<Typography paragraph>
{project.jobDesc}
</Typography>
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>Prerequisites</Typography>
<Typography paragraph>
{project.jobPrereq}
</Typography>
</CardContent>
</Collapse>
</Card>
</Grid>
))}
</Grid>
</div >
);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一种方法是为卡创建单独的组件。这将使您能够将状态添加到组件并控制它们。这是一个最小的示例,展示了如何处理它。
One approach is to create a separate component for the card. This will enable you to add states to the component and control them. Here is a minimal example demonstrating how you can approach it.