【问题标题】:React : How can I open a particular edit/delete window of a card?React:如何打开卡片的特定编辑/删除窗口?
【发布时间】:2021-04-10 22:59:52
【问题描述】:

我在使用更多垂直图标打开编辑/删除窗口时遇到了很多麻烦。我使用了一个图标按钮来显示编辑和删除按钮。有卡片组件,每个卡片组件都有这个图标,当我单击该图标时,它会显示编辑/删除选项,但当我正在映射时,它也会显示所有其他卡片的编辑/删除。当我单击单张卡片的更垂直图标时,它应该只显示该卡片的编辑/删除选项。我怎样才能做到这一点?

代码如下:


ListProducts.js

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)

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    问题

    您正在为所有被映射的状态使用单个 expanded 状态。

    解决方案

    不要使用布尔值来指示元素已展开,请使用与要展开的卡片相关联的内容,例如已传递给处理程序的 id。

    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>
    
                ...
            </>
        )
    }
    

    如果我错过了任何 expanded 使用,它只是与 product.id 的比较,(expanded === product.id)。

    【讨论】:

    • expanded===product.id in collapse 在点击图标时不会打开窗口
    • @ShravaniShinde 你能澄清一下你指的是哪个窗口吗? Collapse 组件基本上只是展开/折叠以显示/隐藏内容。
    • @ShravaniShinde Ack,您正在立即调用点击处理程序:onClick={handleExpandClick(product.id)},但它应该是一个回调:onClick={() =&gt; handleExpandClick(product.id)}。我更新了我的答案。很抱歉没听清楚。
    猜你喜欢
    • 1970-01-01
    • 2016-07-03
    • 2023-04-10
    • 2018-10-11
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    相关资源
    最近更新 更多