Getting sum of items from different states

So I’m creating an app to vote what boardgame players want to play next. The ideas is that there is a drag and drop list column for each of the 4 players and they put the games they want to play in order.

I’ve managed to get the cards to show the “voting value” which is basically the new array length - the item’s current index.

However, what I don’t know how to tackle is how can I get the total score component at the bottom to sum up the correct “voting value” for that game from each of the players?

When you ask a question, don’t forget to include a link to the exercise or project you’re dealing with!

If you want to have the best chances of getting a useful answer quickly, make sure you follow our guidelines about how to ask a good question. That way you’ll be helping everyone – helping people to answer your question and helping others who are stuck to find the question and answer! :slight_smile:

You can create a state object in the App component that will store the total scores for each game. Each time an item is dragged and dropped, you can update these scores in the state object.

import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import SortableColumn from './Components/SortableColumn/SortableColumn';
import TotalScore from './Components/TotalScore/TotalScore';
import { Container, Row } from 'react-bootstrap';
import { initialGames } from './data';
import { useState } from 'react';
import { arrayMove } from '@dnd-kit/sortable';

function App() {
 const [player1Games, setPlayer1Games] = useState(initialGames);
 const [player2Games, setPlayer2Games] = useState(initialGames);
 const [player3Games, setPlayer3Games] = useState(initialGames);
 const [player4Games, setPlayer4Games] = useState(initialGames);
 const [totalScores, setTotalScores] = useState({});

 function handleDragEnd1(event) {
   const {active, over} = event;
   
   if (active.id !== over.id) {
     setPlayer1Games((items) => {
       const activeIndex = items.indexOf(active.id);
       const overIndex = items.indexOf(over.id);
       const newItems = arrayMove(items, activeIndex, overIndex);

       newItems.forEach((game, index) => {
         const points = newItems.length - index;
         updateTotalScores('Player 1', game, points);
       });

       return newItems;
     });
   }
 }

 function handleDragEnd2(event) {
   const {active, over} = event;
   
   if (active.id !== over.id) {
     setPlayer2Games((items) => {
       const activeIndex = items.indexOf(active.id);
       const overIndex = items.indexOf(over.id);
       const newItems = arrayMove(items, activeIndex, overIndex);

       newItems.forEach((game, index) => {
         const points = newItems.length - index;
         updateTotalScores('Player 2', game, points);
       });

       return newItems;
     });
   }
 }

 function handleDragEnd3(event) {
   const {active, over} = event;
   
   if (active.id !== over.id) {
     setPlayer3Games((items) => {
       const activeIndex = items.indexOf(active.id);
       const overIndex = items.indexOf(over.id);
       const newItems = arrayMove(items, activeIndex, overIndex);

       newItems.forEach((game, index) => {
         const points = newItems.length - index;
         updateTotalScores('Player 3', game, points);
       });

       return newItems;
     });
   }
 }

 function handleDragEnd4(event) {
   const {active, over} = event;
   
   if (active.id !== over.id) {
     setPlayer4Games((items) => {
       const activeIndex = items.indexOf(active.id);
       const overIndex = items.indexOf(over.id);
       const newItems = arrayMove(items, activeIndex, overIndex);

       newItems.forEach((game, index) => {
         const points = newItems.length - index;
         updateTotalScores('Player 4', game, points);
       });

       return newItems;
     });
   }
 }

 function updateTotalScores(player, game, points) {
   setTotalScores(prevScores => ({
     ...prevScores,
     [player]: {
       ...prevScores[player],
       [game]: points
     }
   }));
 }

return (
 <div className="App">
   <Container>
     <h1>Vote for a Game</h1>
     <p>Each player should drag and drop the games in the order of how much they would like to play the game. The top game is the one they most want to play, and the lowest is their least favourite.</p>
     <Row>
       <SortableColumn playerName="Player 1" state={player1Games} onDragEnd={handleDragEnd1} />
       <SortableColumn playerName="Player 2" state={player2Games} onDragEnd={handleDragEnd2} />
       <SortableColumn playerName="Player 3" state={player3Games} onDragEnd={handleDragEnd3} />
       <SortableColumn playerName="Player 4" state={player4Games} onDragEnd={handleDragEnd4} />
     </Row>
     <TotalScore state1={player1Games} state2={player2Games} state3={player3Games} state4={player4Games} totalScores={totalScores} />
   </Container>
 </div>
);
}

export default App;

And in the TotalScore component, you can use the total scores to display the total score for each game:

import React from 'react';

function TotalScore

({state1, state2, state3, state4, totalScores}) {
 return (
   <div className='totalScore'> 
     <h4>Total Score:</h4>
     <ul>
       {state1.map(game => <li key={game}>{game}: {totalScores['Player 1'][game]}</li>)}
       {state2.map(game => <li key={game}>{game}: {totalScores['Player 2'][game]}</li>)}
       {state3.map(game => <li key={game}>{game}: {totalScores['Player 3'][game]}</li>)}
       {state4.map(game => <li key={game}>{game}: {totalScores['Player 4'][game]}</li>)}
     </ul>
   </div>
 );
}

export default TotalScore;