简体   繁体   中英

How to pass data out of map function to sibling component in React?

I have a shopping cart which uses map to render several cards based on array objects. Each card contains item price, item quantity which can be increased by clicking the button, and item total price = price * quantity. There is an info bar at the bottom, which I'd like to show total price of all cards as user clicks the add button. Here is a working example: https://codesandbox.io/s/brave-hamilton-4o1l1 ?

Here is the code:

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

Infobar.js:

 import React from 'react'; const Infobar = ({ totalPrice }) => { return ( <div>Total Price: {totalPrice}</div> ) } export default Infobar;

Now the problem is, total price of all items in Infobar does not change (I passed 0 as dummy data). I need to calculate the total price of all items and pass it to Infobar . I have calculated the correct value in _totalPrice in RenderCards, how can I pass _totalPrice to Infobar?

why not just add a new state const [total, setTotal] = useState(0); the same way you set quantity? you set the total where you put your log and pass the total to your Infobar component.

However although it works I see some issues in the way you have put the code, for once why would you create a component inside your home component and not just let Card handle all the logic?

I have updated the Sandbox you need to use internal state to cause a rerender.

You should really take a look at the documentation . At least read 1 - 12 of the Main Concepts section and the section on hooks. There are several parts of the example you provided where you are opting for mutation and imperative statements which will not work with React.

Updated Sanbox

Link

Imperative vs Declarative React

Here are great examples that explain the difference.

Rather than giving specific instructions such as trying to mutate the totalPrice variable opt for useState and useEffect and let your jsx be a result of state and props.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM