Reactjs 反应:如何打开卡片的特定编辑/删除窗口?
在使用更多垂直图标打开编辑/删除窗口时,我遇到了很多麻烦。我使用了一个图标按钮来显示编辑和删除按钮。有卡片组件,每个卡片组件都有此图标,当我单击图标时,它会显示编辑/删除选项,但当我映射时,它也会显示所有其他卡片的编辑/删除。当我点击一张卡的“更垂直”图标时,它应该只显示该卡的编辑/删除选项。我怎样才能做到这一点 代码如下:Reactjs 反应:如何打开卡片的特定编辑/删除窗口?,reactjs,redux,Reactjs,Redux,在使用更多垂直图标打开编辑/删除窗口时,我遇到了很多麻烦。我使用了一个图标按钮来显示编辑和删除按钮。有卡片组件,每个卡片组件都有此图标,当我单击图标时,它会显示编辑/删除选项,但当我映射时,它也会显示所有其他卡片的编辑/删除。当我点击一张卡的“更垂直”图标时,它应该只显示该卡的编辑/删除选项。我怎样才能做到这一点 代码如下: ListProducts.js 从“@material ui/core”导入{makestyle、纸张、卡片、卡片操作、卡片内容、排版、图标按钮、卡片媒体、卡片操作区域、
ListProducts.js
从“@material ui/core”导入{makestyle、纸张、卡片、卡片操作、卡片内容、排版、图标按钮、卡片媒体、卡片操作区域、链接}
从“React”导入React,{useffect,useState}
从“clsx”导入clsx;
从“./FormProduct”导入FormProduct
从“@material ui/core”导入{Grid}
从“@material ui/icons/Add”导入AddIcon
从“@material ui/core/Collapse”导入折叠;
从“@material ui/icons/MoreVert”导入MoreVertIcon;
从“../../components/controls/Button”导入按钮
从“react redux”导入{connect}
从“../../actions”导入{addProduct,listAllProducts,deleteProduct,editProduct}
从“../controls/PopUp”导入弹出窗口
从“../controls/ConfirmDialog”导入ConfirmDialog
从“../../laptop.jpg”导入笔记本电脑
const useStyles=makeStyles(主题=>({
页面内容:{
边距:主题。间距(1),
填充:主题。间距(5),
},
按钮1:{
背景颜色:“#AEB6BF”,
边界半径:“25px”
},
添加按钮:{
位置:'绝对',
右:‘70px’,
顶部:“90px”,
[theme.breakpoints.down('sm'):{
位置:'绝对',
顶部:'75px',
右:“20px”
},
[主题.breakpoints.down('md')]:{
位置:'绝对',
顶部:“80px”,
右:'110px'
},
[主题.breakpoints.down('xs')]:{
位置:'绝对',
顶部:'80px',
右:'95px'
}
},
网格容器:{
marginTop:'10px',
},
根目录:{
最小宽度:275,
[主题.breakpoints.down('xs')]:{
最小宽度:220
}
},
标题:{
尺寸:14,
},
产品:{
[主题.breakpoints.down('md')]:{
marginTop:'20px',
textAlign:“中心”
}
},
pos:{
marginBottom:12,
位置:'绝对',
右:'30px',
顶部:'155px',
[theme.breakpoints.down('sm'):{
位置:'绝对',
左:“15px”,
顶部:'175px'
},
[主题.breakpoints.down('xs')]:{
位置:'绝对',
左:'15px',
顶部:'214px'
}
},
扩展:{
变换:“旋转(0度)”,
marginLeft:'自动',
转换:theme.transitions.create('transform'{
持续时间:theme.transitions.duration.shortest,
}),
},
expandOpen:{
变换:“旋转(180度)”,
},
莫尔维特康:{
位置:'绝对',
顶部:'40px'
},
卡片:{
位置:'绝对',
顶部:'325px',
左:'330px',
[theme.breakpoints.down('sm'):{
位置:'绝对',
顶部:'325px',
左:'280px'
},
光标:'指针'
},
链接:{
marginLeft:'280px',
[theme.breakpoints.down('sm'):{
边缘左侧:'150px'
}
},
链接1:{
text装饰:'无',
颜色:“#808080!重要”,
textAlign:“中心”
},
链接标签:{
字体大小:'16px',
填充:“3px”
},
行动:{
显示:“flex”,
'& > *': {
边距:主题。间距(3),
宽度:主题。间距(12),
高度:主题。间距(9),
},
位置:'绝对',
左:'200px'
},
[theme.breakpoints.down('sm'):{
位置:'绝对',
左:'280px'
}
}))
const ListProducts=(道具)=>{
const[openPopUp,setOpenPopUp]=useState(false)
const[confirmDialog,setConfirmDialog]=useState({isOpen:false,title:'',confirmationmsg:'Confirmation'})
const[edited,setEdited]=useState(null)
常量[计数器,设置计数器]=使用状态(0)
const[expanded,setExpanded]=React.useState(false);
const handleExpandClick=(id)=>{
如果(id)
setExpanded(!expanded);
};
常量类=useStyles()
const addOrEdit=(产品,重置表单)=>{
如果(product.id==0){
道具添加产品(产品)
设置计数器(计数器+1)
}
否则{
props.editProduct(product.id,product)
}
重置表单()
setOpenPopUp(错误)
}
const renderProduct=(id)=>{
道具.删除产品(id)
setConfirmDialog(错误)
如果(计数器>0){
设置计数器(计数器-1)
}
否则{
设置计数器(0)
}
}
const openInPopUp=(产品)=>{
设置编辑(产品)
setOpenPopUp(真)
}
useffect(()=>{
props.listAllProducts()
}, [])
返回(
所有产品({counter})
setOpenPopUp(真)}/>
{props.products&&props.products.map((产品,索引)=>{
返回
产品名称:{Product.Name}
产品价格:{Product.Price}
import { makeStyles, Paper, Card, CardActions, CardContent, Typography, IconButton,CardMedia, CardActionArea, Link } from '@material-ui/core'
import React, { useEffect, useState } from 'react'
import clsx from 'clsx';
import FormProduct from './FormProduct'
import { Grid } from '@material-ui/core'
import AddIcon from '@material-ui/icons/Add'
import Collapse from '@material-ui/core/Collapse';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import Button from '../../components/controls/Button'
import { connect } from 'react-redux'
import { addProduct, listAllProducts, deleteProduct, editProduct } from '../../actions'
import PopUp from '../controls/PopUp'
import ConfirmDialog from '../controls/ConfirmDialog'
import laptop from '../../laptop.jpg'
const useStyles = makeStyles(theme => ({
pageContent: {
margin: theme.spacing(1),
padding: theme.spacing(5),
},
button1: {
backgroundColor: '#AEB6BF',
borderRadius: '25px'
},
addbutton: {
position: 'absolute',
right: '70px',
top: '90px',
[theme.breakpoints.down('sm')]: {
position: 'absolute',
top: '75px',
right: '20px'
},
[theme.breakpoints.down('md')]: {
position: 'absolute',
top: '80px',
right: '110px'
},
[theme.breakpoints.down('xs')]:{
position:'absolute',
top:'80px',
right:'95px'
}
},
gridcontainer: {
marginTop: '10px',
},
root: {
minWidth: 275,
[theme.breakpoints.down('xs')]:{
minWidth:220
}
},
title: {
fontSize: 14,
},
product:{
[theme.breakpoints.down('md')]:{
marginTop:'20px',
textAlign:'center'
}
},
pos: {
marginBottom: 12,
position: 'absolute',
right: '30px',
top: '155px',
[theme.breakpoints.down('sm')]: {
position: 'absolute',
left: '15px',
top: '175px'
},
[theme.breakpoints.down('xs')]:{
position:'absolute',
left:'15px',
top:'214px'
}
},
expand: {
transform: 'rotate(0deg)',
marginLeft: 'auto',
transition: theme.transitions.create('transform', {
duration: theme.transitions.duration.shortest,
}),
},
expandOpen: {
transform: 'rotate(180deg)',
},
moreverticon:{
position:'absolute',
top:'40px'
},
card:{
position:'absolute',
top:'325px',
left:'330px',
[theme.breakpoints.down('sm')]:{
position:'absolute',
top:'325px',
left:'280px'
},
cursor:'pointer'
},
links:{
marginLeft:'280px',
[theme.breakpoints.down('sm')]:{
marginLeft:'150px'
}
},
link1:{
textDecoration:'none',
color:'#808080 !important',
textAlign:'center'
},
linktag:{
fontSize:'16px',
padding:'3px'
},
cardaction:{
display: 'flex',
'& > *': {
margin: theme.spacing(3),
width: theme.spacing(12),
height: theme.spacing(9),
},
position:'absolute',
left:'200px'
},
[theme.breakpoints.down('sm')]:{
position:'absolute',
left:'280px'
}
}))
const ListProducts = (props) => {
const [openPopUp, setOpenPopUp] = useState(false)
const [confirmDialog, setConfirmDialog] = useState({ isOpen: false, title: '', confirmationmsg: 'Confirmation' })
const [edited, setEdited] = useState(null)
const [counter, setCounter] = useState(0)
const [expanded, setExpanded] = React.useState(false);
const handleExpandClick = (id) => {
if(id)
setExpanded(!expanded);
};
const classes = useStyles()
const addOrEdit = (product, resetForm) => {
if (product.id == 0) {
props.addProduct(product)
setCounter(counter + 1)
}
else {
props.editProduct(product.id, product)
}
resetForm()
setOpenPopUp(false)
}
const renderProduct = (id) => {
props.deleteProduct(id)
setConfirmDialog(false)
if (counter > 0) {
setCounter(counter - 1)
}
else {
setCounter(0)
}
}
const openInPopUp = (product) => {
setEdited(product)
setOpenPopUp(true)
}
useEffect(() => {
props.listAllProducts()
}, [])
return (
<>
<Paper className={classes.pageContent} >
<Typography variant='h5' component='h5' className={classes.product}>All Products({counter})</Typography>
<Button text='Add Product'
variant='outlined'
startIcon={<AddIcon />}
className={classes.addbutton}
onClick={() => setOpenPopUp(true)} />
<Grid container spacing={2} className={classes.gridcontainer}>
{props.products && props.products.map((product, index) => {
return <Grid item xs={12} sm={6} md={4} lg={3} key={index + 1} className={classes.griditem}>
<Card className={classes.root}>
<CardActionArea>
<CardMedia
component="img"
alt="Laptop"
height="140"
image={laptop}
title="Laptop"
/>
<CardContent>
<Typography variant='h3' component='h3' className={classes.title} color="textSecondary" gutterBottom>
Product Name : {product.name}
</Typography>
<Typography className={classes.pos} color="textSecondary" variant='p' >
Product Price : {product.price}
</Typography>
<Typography variant="body2" component="p">
Product Category : {product.category}
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<div className={classes.card}>
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={handleExpandClick(product.id)}
aria-expanded={expanded}
aria-label="show more"
>
<MoreVertIcon/>
</IconButton>
</div>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardActions>
<div className={classes.cardaction}>
<Paper elevation={3} className={classes.links} variant='outlined'>
<div>
<Link className={classes.link1}
onClick={() => openInPopUp(product)}
><Typography className={classes.linktag}>Edit</Typography></Link>
</div>
<div>
<Link className={classes.link1}
onClick={() => setConfirmDialog({
isOpen: true, onConfirmDialog: () => renderProduct(product.id),
title: `Are you sure you want to delete this product? : ${product.name}`
})}
><Typography className={classes.linktag}>Delete</Typography></Link>
</div>
</Paper>
</div>
</CardActions>
</Collapse>
</Card>
</Grid>
})}
</Grid>
</Paper>
<PopUp openPopUp={openPopUp}
setOpenPopUp={setOpenPopUp}
title='Product Form'>
<FormProduct
addOrEdit={addOrEdit}
edited={edited}
title='Hello'
/>
</PopUp>
<ConfirmDialog title={confirmDialog.title}
confirmDialog={confirmDialog}
setConfirmDialog={setConfirmDialog}
confirmationmsg={confirmDialog.confirmationmsg}
/>
</>
)
}
const mapStateToProps = (state) => {
return { products: Object.values(state.products).reverse() }
}
export default connect(mapStateToProps, { listAllProducts: listAllProducts, addProduct: addProduct, deleteProduct: deleteProduct, editProduct: editProduct })(ListProducts)
const ListProducts = (props) => {
...
const [expanded, setExpanded] = React.useState(null); // <-- null state
const handleExpandClick = (id) => {
setExpanded(expandedId => id === expandedId ? null : id); // toggle off or set new
};
...
return (
<>
<Paper className={classes.pageContent} >
...
<Grid container spacing={2} className={classes.gridcontainer}>
{props.products && props.products.map((product, index) => {
return <Grid item xs={12} sm={6} md={4} lg={3} key={index + 1} className={classes.griditem}>
<Card className={classes.root}>
...
<CardActions>
<div className={classes.card}>
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={() => handleExpandClick(product.id)} // <-- fix callback
aria-expanded={expanded === product.id}
aria-label="show more"
>
<MoreVertIcon/>
</IconButton>
</div>
</CardActions>
<Collapse in={expanded === product.id} timeout="auto" unmountOnExit>
...
</Collapse>
</Card>
</Grid>
})}
</Grid>
</Paper>
...
</>
)
}