【问题标题】:How to pass data out of map function to sibling component in React?如何将数据从映射函数传递到 React 中的兄弟组件?
【发布时间】:2020-09-17 21:19:33
【问题描述】:

我有一个购物车,它使用map 根据数组对象呈现多张卡片。每张卡片包含商品价格、可通过点击按钮增加的商品数量、商品总价=价格*数量。底部有一个信息栏,我想在用户单击添加按钮时显示所有卡片的总价格。这是一个工作示例:https://codesandbox.io/s/brave-hamilton-4o1l1?

代码如下:

Home.js:

import React, {useState} from 'react';
import Card from './Card';
import Infobar from './Infobar';

const Home = () => {
    const dummyData = [
        {
            id: 1,
            title: 'hat',
            price: 10
        },
        {
            id: 2,
            title: 'tshirt',
            price: 11
        }
    ]

    const [quantity, setQuantity] = useState([]);

    const changeItemQuantity = (id, itemQty) => {
        let _newState = [...quantity];
        let _itemInfo = _newState.find(item => item.id === id);
        if (_itemInfo !== undefined) {
            _itemInfo.itemQty += 1;
        } else {
            _newState.push({ id: id, itemQty: itemQty + 1 });
        };

        setQuantity(_newState);
    }

    const RenderCards = () => {
        let _totalPrice = 0;
        return (
            dummyData.map(
                (d) => {
                    const stateItem = quantity.find(item => item.id === d.id);
                    const itemQty = stateItem ? stateItem.itemQty : 0;
                    _totalPrice += d.price * itemQty;
                    console.log(_totalPrice); // correct value to send to Infobar
                    return (
                        <Card
                            key={d.id}
                            id={d.id}
                            title={d.title}
                            price={d.price}
                            quantity={itemQty}
                            changeItemQuantity={changeItemQuantity}
                            itemTotalPrice={d.price * itemQty}
                        />
                    )
                }
            )
        )
    }
    return (
        <>
            <RenderCards/>
            <Infobar totalPrice={0}/> // here Infobar should take total price as an input
        </>
    )
}

export default Home;

Card.js:

import React from 'react';

const Card = ({ id, title, price, quantity, changeItemQuantity, itemTotalPrice }) => {
    return (
        <>
            <div key={id}>
                <p>{id}. {title}</p>
                <p>Quantity: {quantity}</p>
                <p>Price: {price}</p>
                <p>Item total price: {itemTotalPrice}</p>
                <button onClick={() => changeItemQuantity(id, 0)}>Add item</button>
            </div>
        </>
    )
}

export default Card

信息栏.js:

import React from 'react';

const Infobar = ({ totalPrice }) => {
    return (

        <div>Total Price: {totalPrice}</div>

    )
}

export default Infobar;

现在的问题是,信息栏中所有项目的总价格没有变化(我将 0 作为虚拟数据传递)。我需要计算所有商品的总价并将其传递给Infobar。我已经计算出 RenderCards 中 _totalPrice 中的正确值,如何将 _totalPrice 传递给 Infobar?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    我有updated the Sandbox,你需要使用内部状态来重新渲染。

    你真的应该看看documentation。至少阅读 Main Concepts 部分的 1 - 12 和 hooks 部分。在您提供的示例的几个部分中,您选择了不适用于 React 的突变和命令式语句。

    更新的 Sanbox

    Link

    命令式 vs 声明式 React

    Here are great examples 解释了差异。

    而不是给出具体的指令,比如尝试改变totalPrice 变量,选择useStateuseEffect,让你的jsx 成为状态和道具的结果。

    【讨论】:

    • 我在询问之前尝试了您的解决方案,在地图内设置状态很直观,但我没有这样做的原因是这个控制台错误:index.js:1 警告:无法更新组件( Home) 同时渲染不同的组件 (RenderCards)。要在 RenderCards 中找到错误的 setState() 调用,请按照 ... 中所述的堆栈跟踪进行操作
    • 检查沙箱,虽然代码有效,但每次点击按钮都会产生控制台错误。
    • 这是由于您渲染卡片的方式。我很快就会发布一个更新的沙盒
    • 另外,您能否详细说明一下“我正在选择不适用于 React 的突变和命令式语句”?
    【解决方案2】:

    为什么不直接添加一个新状态const [total, setTotal] = useState(0);,就像设置数量一样?您在放置日志的位置设置总数并将总数传递给您的信息栏组件。

    但是,尽管它可以工作,但我发现您放置代码的方式存在一些问题,为什么您要在主组件中创建一个组件,而不是让 Card 处理所有逻辑?

    【讨论】:

    • 我在询问之前尝试了您的第一个解决方案并收到此控制台错误:在呈现不同组件时无法更新组件。
    • 之所以把逻辑放在Home里,是因为除了Card之外,还有一些共享数据需要传递给其他组件,所以我试着把所有逻辑都放在Home里,并传递数据一直到它的孩子。
    猜你喜欢
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2021-06-10
    • 2019-12-30
    相关资源
    最近更新 更多