Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMatt Rabe
2,950 PointsREMOVE_PLAYER and selectedPlayerIndex bug, with solution
Because this project uses index
to track players instead of some uid, a bug occurs when the user removes a player whose index
is <= the current selectedPlayerIndex
. Reproduce it:
- Open the app
- Click on the last player
- Observe the player's details correctly displayed in the PlayerDetail component at bottom
- Click the "X" next to the last player to remove that player.
- Observe error in console:
Uncaught TypeError: Cannot read property 'name' of undefined
Also:
- Open the app
- Click on the first player
- Observe the player's details correctly displayed in the PlayerDetail component at bottom
- Click the "X" next to the first player to remove that player.
- Observe that the PlayerDetail component now unexpectedly shows the details for the second player, even though we never clicked on that player.
This is because the REMOVE_PLAYER reducer does not return an updated selectedPlayerIndex
, even though the landscape of the indexes has been changed by removing a player.
In a more robust app the appropriate way to handle this would be to use some UID instead of indexes, but for the purposes of this project, a simple bugfix would be to use a bit of logic to return an updated selectedPlayerIndex
in the REMOVE_PLAYER reducer like so:
case PlayerActionTypes.REMOVE_PLAYER:
return {
...state,
players: [
...state.players.slice(0, action.index),
...state.players.slice(action.index + 1)
],
selectedPlayerIndex: (state.selectedPlayerIndex === action.index ? -1 : (state.selectedPlayerIndex > action.index ? state.selectedPlayerIndex - 1 : state.selectedPlayerIndex)),
};
This snippet ensures that if the user removes the currently selected player selectedPlayerIndex
will become -1 (thereby hiding the PlayerDetail component), and if the user removes a player with an index that is less than the index of the currently selected player selectedPlayerIndex
will be adjusted down by one to accommodate for the shift in indexes.
Matt Rabe
2,950 PointsThanks for the help getting this thread correctly attached, Steven. The other thread is now deleted :)
3 Answers
Adam Beer
11,314 PointsThanks your solution! It's great, now working fine!
Cristina Rosales
10,929 PointsMy fix was way simpler. I just put a span tag around the {name} in Player and had the onClick event on the new span element.
like so:
<span onClick={()=>props.selectPlayer(props.index)}>{props.name}</span>
Birthe Vandermeeren
17,146 PointsThat's what I thought first too, but this doesn't always display the details you'd expect either. Take for example: You select the first player, then remove it, then it displays the details of the new first player, while you expect it to show the "Click ..." text again.
Birthe Vandermeeren
17,146 PointsI agree that in a more robust app the appropriate way to handle this would be to use some UID instead of indexes. While I understand your solution, I went with a simpeler one: setting the selectedPlayerIndex back to -1 when a player gets removed. Now the "Click ..." text always appears when you remove one of the players.
Steven Parker
231,275 PointsSteven Parker
231,275 PointsThere ya go, now it's fully linked in. Don't forget to also notify the staff.