【问题标题】:React - Why Props do not updateReact - 为什么道具不更新
【发布时间】:2021-08-20 16:10:14
【问题描述】:

我刚刚注意到我为我的 PayPal 沙盒发送的道具没有更新。

上下文:

我有一个添加购物车页面,用户可以在其中增加/减少他们在购物车中的产品数量。

我还显示购物车的总金额。

这两个值:Quantity 和 Total 通过 props 发送到 PayPal 组件(A 按钮)。

除非用户更改数量,否则我的 PayPal 按钮不会考虑这些新值。所以我必须手动刷新页面。这是个大问题。

这是我的代码:

export default function PanierPage() {

    let MonTotal = '';

    const classPanier = PanierStyles();

        const [total, setTotal] = useState([])
        
        // Récupération des détails des paniers
        const [paniers, setPaniers] = useState([])
        const getPaniersDetails = () => [
            getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
                setPaniers(response.data)
            }).catch(err => console.log(err))
        ]

        const handleIncrement = (id, quantite) => {
                updateQuantite(id, quantite + 1 ).then(response => {
                    getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
                        setPaniers(response.data)
                    }).catch(err => console.log(err))
                    getTotal(JSON.parse(localStorage.getItem('User')).id).then(response => {
                        setTotal(response.data)
                    }).catch(err => console.log(err)) 
            }).catch(err => console.log(err))
        }
        
        const handleDecrement = (id, quantite) => {
            updateQuantite(id, quantite - 1 ).then(response => {
                getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
                    setPaniers(response.data)
                }).catch(err => console.log(err))
                getTotal(JSON.parse(localStorage.getItem('User')).id).then(response => {
                    setTotal(response.data)
                }).catch(err => console.log(err))
            }).catch(err => console.log(err))
        }

        const SupprPanier = (id) => {
            deletePanier(id).then(response => {
                getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
                    setPaniers(response.data)
                }).catch(err => console.log(err))
                getTotal(JSON.parse(localStorage.getItem('User')).id).then(response => {
                    setTotal(response.data)
                }).catch(err => console.log(err))
            }).catch(err => console.log(err))
        }


        // Affichage des détails des paniers 
        const paniersAffichage = paniers.map((panier) => (
            <Grid container style={{justifyContent:'center', padding: '1em'}}>
                <Card key={panier.PAN_ID} style={{height: '100%', display: 'flex', flexDirection: 'row'}} variant='outlined'>

                    <CardHeader title={panier.PRO_NOM}/>

                        <CardMedia style={{height: 150, width: 150, marginLeft: 'auto', marginRight: 'auto'}} image={`http://localhost:8090/${panier.PRO_URL}`}/>

                        <Grid direction="row" justify="center" alignItems="center">
                            <CardContent>
                                {panier.PAN_QUANTITE === panier.PRO_QTESTOCK
                                ?
                                    <Button variant='outlined' color="primary" disabled onClick={() => handleIncrement(panier.PAN_ID, panier.PAN_QUANTITE)}> + </Button>
                                :
                                    <Button variant='outlined' color="primary" onClick={() => handleIncrement(panier.PAN_ID, panier.PAN_QUANTITE)}> + </Button>
                                }
                                <Typography style={{textAlign: 'center'}}>
                                    {panier.PAN_QUANTITE}
                                </Typography>

                                {panier.PAN_QUANTITE === 1 
                                ?
                                    <Button variant='outlined' color="secondary" disabled onClick={() => handleDecrement(panier.PAN_ID, panier.PAN_QUANTITE)}> - </Button>
                                :
                                    <Button variant='outlined' color="secondary" onClick={() => handleDecrement(panier.PAN_ID, panier.PAN_QUANTITE)}> - </Button>
                                }
                            </CardContent>
                        </Grid>
                        <Box>
                            <Grid container direction="row" justify="center" alignItems="center" >
                                <Typography style={{textAlign: 'center'}}>
                                    {panier.PRO_PRIX} €
                                </Typography>
                                <CardActions>
                                    <Button onClick={() => SupprPanier(panier.PAN_ID)} className={classPanier.iconDelete}><DeleteIcon/></Button>
                                </CardActions>
                            </Grid>
                        </Box>
                </Card>
            </Grid>
        ));
        
        
        const PanierTotal = () => {
            getTotal(JSON.parse(localStorage.getItem('User')).id).then(response => {
                setTotal(response.data)
            }).catch(err => console.log(err))
        }

        const TotalAffiche = total.map((total) => (
            <Grid style={{color: 'white', marginTop: '2%', marginBottom: '2%',}}>
                Montant total de votre panier : {total.TOTAL} €
            </Grid>
        ))

        // Chargement des produits
        useEffect(() => {
            getPaniersDetails();
            PanierTotal();
        }, [])

    return (
            <>
                {paniersAffichage}
                <Grid container style={{justifyContent:'center'}}>
                {TotalAffiche}
                <Grid style={{marginLeft: '2%'}}>
                    {(total.length > 0 && paniers.length > 0) && <PayPal prixTotal={total[0].TOTAL} paniers={paniers} />}
                </Grid>
                </Grid>
            </>
        );
}

还有我的 PayPal 按钮:

export default function Paypal({prixTotal, paniers}) 
{
    
    const PDFGeneration = () => {
        var doc = new jsPDF('p','px','a4','false');
        var lesPaniers = paniers.map(panier => [panier.PRO_NOM, panier.PAN_QUANTITE, panier.PRO_PRIX ]);

        doc.text(10,15,'Résumé de votre commande : ');
        doc.autoTable({
            theme: 'grid',
            startY: 20,
            head: [['Nom', 'Quantité', 'Prix (€)']],
            body: lesPaniers,
        });
        doc.text(10,120,`Total de la commande : ${prixTotal} €`);
        doc.text(10,150,'A la prochaine fois !');
        doc.save('CommandeInfo.pdf');
    }

    const paypal = useRef()

    useEffect(() => {

        window.paypal.Buttons({
            style: {
                color: 'gold',
            },
            createOrder: (data, actions) => {
                return actions.order.create({
                    intent: 'CAPTURE',
                    purchase_units: [
                        {
                            description: 'Transaction du site E-Commerce.',
                            amount: {
                                currency_code: 'EUR',
                                value: prixTotal
                            }
                        }]
                })
            },
            onApprove: (data, actions) => {
                createCommande(true).then(response => {
                    PDFGeneration();
                    window.location.reload(false);
                });
                return actions.order.capture();
            },
            onCancel: (data, actions) => {
                console.log("Transaction annulé");
                console.log(prixTotal)
            }
        }).render(paypal.current)
    }, [])

    return (
        <div>
            <div ref={paypal}></div>
        </div>
    );
}

但是,购物车中的每个产品都分配有一个键,通常应该触发重新呈现 PayPal 的值。

如果有人能解释/找到我的问题,我将不胜感激!再次感谢您的宝贵时间。

【问题讨论】:

    标签: javascript reactjs paypal


    【解决方案1】:

    在您的 PayPal 组件中,您没有将任何列表作为第二个参数传递给 useEffect 挂钩。这样它只会在组件安装时执行。如果您想在道具更改时更新它,您应该将需要触发它的道具作为第二个参数列表传递:

    export default function Paypal({prixTotal, paniers}) 
    {
        // ...
        useEffect(() => {
            if (window.paypalBtn) window.paypalBtn.close();
            window.paypalBtn = window.paypal.Buttons({
                // ...
            });
            window.paypalBtn.render(paypal.current)
        }, [prixTotal, paniers]);
        // ...
    }
    

    【讨论】:

    • 感谢您的回答,但它没有按计划工作。使用您的方法,每次用户更改值时,我的页面上都会出现一个新的“PayPal”按钮。确实,这个新按钮包含新值,但是......我真的不想每次更改值时都有一个新按钮^^
    • 那么在这种情况下,您将需要更改添加按钮的逻辑。也许删除旧的并显示新的?
    • 我不认为拥有“多个按钮”是个好主意。我的按钮逻辑非常简单:{(total.length > 0 && paniers.length > 0) && }。一定有别的办法。
    • 不,我的意思是 useEffect 中的逻辑。我更新了我的答案。如果按钮已经渲染,请尝试存储并关闭()按钮,然后显示新按钮。
    • 好的,它现在可以工作了,即使您可以清楚地看到按钮消失并重新出现......嗯,这是一种方法!谢谢你的回答!
    猜你喜欢
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 2017-12-26
    • 2018-02-04
    相关资源
    最近更新 更多