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>

            ...
        </>
    )
}