I've got a form ponent, where you can add an input on click of the button, creating a new team, where you can add players for.
The problem is, that if you fill in a value, all inputs will be filled with that value, because it is using the same state. My guess is to make a new state value for each new team (something like 'input' + index, which would result in states like input0, input1, input2, etc).
Though I can't implement this using React Hooks as you have to declare your state at first, and assign a set function to it.
Any thought on how I can implement this behaviour?
I've got a form ponent, where you can add an input on click of the button, creating a new team, where you can add players for.
The problem is, that if you fill in a value, all inputs will be filled with that value, because it is using the same state. My guess is to make a new state value for each new team (something like 'input' + index, which would result in states like input0, input1, input2, etc).
Though I can't implement this using React Hooks as you have to declare your state at first, and assign a set function to it.
Any thought on how I can implement this behaviour?
Share Improve this question asked Mar 18, 2019 at 22:12 JurJur 1852 gold badges3 silver badges10 bronze badges3 Answers
Reset to default 7Here's just one solution that's pretty straightforward, keeping track of values in an array, just to illustrate that hooks don't make anything more difficult:
function App() {
let [inputs, setInputs] = useState([""]);
return (
<div className="App">
<button onClick={() => setInputs(inputs.concat(""))}>Add input</button>
<form>
{inputs.map((value, i) => (
<div key={i}>
<label>Input {i + 1}</label>
<input
value={value}
onChange={e =>
setInputs(
inputs.map((value, j) => {
if (i === j) value = e.target.value;
return value;
})
)
}
/>
</div>
))}
</form>
</div>
);
}
codesandbox
Structure your state to be like:
const teams = [
{ name: "Team 1", players: [ /* ... */ ] },
{ name: "Team 2", players: [ /* ... */ ] },
/* ... */
];
I encourage you to use useReducer() hook, it fits so well for your case! It's a bit boilerplaty, but with clean and very understandable code.
function reducer(state, action) {
switch (action.type) {
case 'addPlayer':
// find needed team and push player object there
case 'addTeam':
// push new team object into state
default:
throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, teams);
Structure of state may vary, for example you can use keyed object for teams it doesn't matter.
I would structure the state like this:
// initial state
state = { teams: [] }
where each team object has a name and has an array of players:
{ name: "team1", players: ["player1", "player2"] }
So the state may end up looking like this:
{ teams: [
{ name: "team1", players: ["player1", "player2"] },
{ name: "team2", players: ["player3", "player4"] },
{ name: "team3", players: ["player5", "player6"] }
]
}