2

I have been working with React Hooks for a while, but the biggest problem for me is working with arrays.

I am making a register form for teams. Teams have players (array of strings).

The user should be able to add a team, and for each team, an input is shown with the current members in the team displayed above the input.

My question: How do I set the state of a nested array with React Hooks?

On the button click, it should (for now) add a string to the players array of the current team.

My Code:

interface ITeam {
    id: string;
    players: Array<string>;
}


export default function Team() {
const [teams, setTeams] = useState<Array<ITeam>>([{id: '1', players: ['a', 'b']}]);

return (
    <div>
        {teams.map((team, teamIndex) => {
            return (
                <div key={teamIndex}>
                    <h2>Team {teamIndex + 1}</h2>
                    <ul>
                        {team.players.map((player, playerIndex) => {
                            return (
                                <div key={playerIndex}>
                                    {player}
                                </div>
                            );
                        })}
                    </ul>
                    <button onClick={() => setTeams([...teams, team.players.concat('c')])}>Add player</button>
                </div>
            );
        })}
    </div>
);
}

1 Answer 1

7

You need to make use of team index and update that particular teams value using spread syntax and slice like

  function addPlayer(index) {
    setTeams(prevTeams => {
      return [ ...prevTeams.slice(0, index), {...prevTeams[index], players: [...prevTeams[index].players, "c"] }, ...prevTeams.slice(index+1)];
    });
  }

or better you can just use map to update

function addPlayer(index) {
  setTeams(prevTeams => {
    return prevTeam.map((team, idx) => {
      if(index === idx) {
        return {...prevTeams[index], players: [...prevTeams[index].players, "c"]}
      } else {
        return team;
      }
    })
  });
}

const { useState } = React;

function Team() {
  const [teams, setTeams] = useState([{ id: "1", players: ["a", "b"] }]);

  function addPlayer(index) {
    setTeams(prevTeams => {
      return [ ...prevTeams.slice(0, index), {...prevTeams[index], players: [...prevTeams[index].players, "c"] }, ...prevTeams.slice(index+1)];
    });
  }

  return (
    <div>
      {teams.map((team, teamIndex) => {
        return (
          <div key={teamIndex}>
            <h2>Team {teamIndex + 1}</h2>
            <ul>
              {team.players.map((player, playerIndex) => {
                return <div key={playerIndex}>{player}</div>;
              })}
            </ul>
            <button onClick={() => addPlayer(teamIndex)}>Add player</button>
          </div>
        );
      })}
    </div>
  );
}

ReactDOM.render(<Team />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.