1 00:00:00,440 --> 00:00:01,500 How did it go? 2 00:00:01,500 --> 00:00:04,550 Were you able to build the highest score feature? 3 00:00:04,550 --> 00:00:07,450 Don't worry if you didn't complete everything. 4 00:00:07,450 --> 00:00:10,541 You can watch my solution, compare it to what you wrote and 5 00:00:10,541 --> 00:00:12,380 then try to recreate it yourself. 6 00:00:14,530 --> 00:00:19,440 First, let's create a new file named icon.js. 7 00:00:19,440 --> 00:00:22,369 We'll import react, at the top of the file, and 8 00:00:22,369 --> 00:00:24,880 create a function component named Icon. 9 00:00:25,880 --> 00:00:28,350 Our component will render the SVG element, 10 00:00:28,350 --> 00:00:31,030 that was provided in the teachers notes below. 11 00:00:32,840 --> 00:00:36,415 And at the bottom, we'll export our component. 12 00:00:36,415 --> 00:00:41,573 To apply the gold fill color and scaling animation to the crown, 13 00:00:41,573 --> 00:00:46,347 we need to add the class is-high-score to the SVG element, but 14 00:00:46,347 --> 00:00:50,950 we only want to add it if the player has the highest score. 15 00:00:52,080 --> 00:00:57,360 So eventually Icon will accept the prop named isHighScore. 16 00:00:57,360 --> 00:01:02,410 That will equal true if the player has the highest score, and false if it does not. 17 00:01:04,510 --> 00:01:11,425 Let's pass className a ternary expression to render the class is-high-score, 18 00:01:11,425 --> 00:01:17,420 if isHighScores is true, otherwise render null or no class attribute. 19 00:01:18,910 --> 00:01:23,250 Let's not forget to validate the Icon component's props. 20 00:01:23,250 --> 00:01:28,720 Let's import Prop Types, at the top with import PropTypes, from prop-types. 21 00:01:30,310 --> 00:01:35,390 And right below the function, let's give Icon the property propTypes. 22 00:01:35,390 --> 00:01:39,390 And set it equal to an object. The isHighScore prop, 23 00:01:39,390 --> 00:01:43,290 the Icon accepts should be a boolean. 24 00:01:43,290 --> 00:01:49,507 So I'll write, isHighScore: and set it to PropTypes.bool, 25 00:01:49,507 --> 00:01:54,720 and let's make it required by adding .isRequired. 26 00:01:54,720 --> 00:01:57,701 Our Icon component is complete. 27 00:01:57,701 --> 00:02:02,431 In Player.js I'll import the Icon component with 28 00:02:02,431 --> 00:02:05,515 import Icon from dot slash Icon. 29 00:02:05,515 --> 00:02:10,961 Then display the icon component in the player components 30 00:02:10,961 --> 00:02:16,520 JSX right below the remove player button. Player component 31 00:02:16,520 --> 00:02:21,513 will also accept the isHighScore prop to pass down to 32 00:02:21,513 --> 00:02:26,750 the Icon component with isHighScore = isHighScore. 33 00:02:26,750 --> 00:02:31,961 Also, let's not forget to add the isHighScore prop to the bottom 34 00:02:31,961 --> 00:02:37,362 of the Player.propTypes object and set it to PropTypes.Bool and 35 00:02:37,362 --> 00:02:40,890 make it required by adding .isRequired. 36 00:02:42,740 --> 00:02:45,990 Awesome, the crown icons are displaying. 37 00:02:45,990 --> 00:02:49,800 Now we're going to get started on the highest score feature. 38 00:02:49,800 --> 00:02:51,760 So let's think about this. 39 00:02:51,760 --> 00:02:55,888 We need to know what's the highest score out of all the players. 40 00:02:55,888 --> 00:02:59,876 To do that, we'll need to look through the player's array and 41 00:02:59,876 --> 00:03:03,500 store the highest score somehow either as a ref or state. 42 00:03:04,800 --> 00:03:09,230 And we want to do this every time the score changes to make sure we have 43 00:03:09,230 --> 00:03:11,810 the latest highest score. 44 00:03:11,810 --> 00:03:16,113 So as you might remember, we actually learned about a tool that will help us do 45 00:03:16,113 --> 00:03:18,380 this and that's react useEffect hook. 46 00:03:19,870 --> 00:03:22,560 Under the previous player ID ref. 47 00:03:22,560 --> 00:03:26,600 Let's write out our useEffect hook and pass it an arrow function. 48 00:03:27,620 --> 00:03:32,128 First, we'll create an array that stores all the player scores by 49 00:03:32,128 --> 00:03:35,120 calling the map method on the player state. 50 00:03:36,720 --> 00:03:40,890 For each player we want map to return the player's score. 51 00:03:40,890 --> 00:03:44,990 So let's write player => player.score. 52 00:03:46,130 --> 00:03:51,270 We can use the Math.max function to return the largest score value, 53 00:03:51,270 --> 00:03:54,430 but how should we store that? 54 00:03:54,430 --> 00:03:56,590 As a ref or as a state? 55 00:03:56,590 --> 00:04:03,840 We know useEffect will run our side effect after the component renders. 56 00:04:03,840 --> 00:04:06,045 If the high score value changes, 57 00:04:06,045 --> 00:04:10,070 we want to trigger another render to update the crown icon. 58 00:04:11,180 --> 00:04:16,949 As you might remember, one of the differences between the useRef hook and 59 00:04:16,949 --> 00:04:22,920 the useState hook is that useState causes a re-render while useRef does not. 60 00:04:24,770 --> 00:04:29,999 Under the player state, we'll use the useState hook to create a state 61 00:04:29,999 --> 00:04:34,890 called highScore and the function to update it as setHighScore. 62 00:04:36,800 --> 00:04:41,915 Back in our useEffect hook, we'll set the highScore state 63 00:04:41,915 --> 00:04:46,724 to the max score by passing setHighScore Math.max and 64 00:04:46,724 --> 00:04:51,042 pass it all the scores using the spread operator. 65 00:04:51,042 --> 00:04:55,468 The way the code is written now react will run our side 66 00:04:55,468 --> 00:04:59,890 effect function after every single render. 67 00:04:59,890 --> 00:05:04,310 However, we only need it to run when the player score is updated. 68 00:05:05,530 --> 00:05:11,070 So let's add a dependency array as a second argument to the useEffect hook. 69 00:05:11,070 --> 00:05:16,411 So that only when the player state changes will the side effect run. 70 00:05:16,411 --> 00:05:20,731 Let's check if our useEffect hook is working properly. 71 00:05:20,731 --> 00:05:23,338 When we increase a player score, 72 00:05:23,338 --> 00:05:27,909 we can see in React dev tools the highScore state updates. 73 00:05:27,909 --> 00:05:32,989 Our icon component needs to receive the isHighScore prop that will be 74 00:05:32,989 --> 00:05:38,870 true if the player has the highest score, and false if it doesn't. 75 00:05:38,870 --> 00:05:43,732 So in the file App.js, I'll scroll down, to the Player component. 76 00:05:43,732 --> 00:05:49,178 The Player component will receive a Boolean prop to determine whether or 77 00:05:49,178 --> 00:05:51,510 not to display the gold crown. 78 00:05:53,400 --> 00:05:59,480 In the map function, pass the player component a prop named isHighScore. 79 00:05:59,480 --> 00:06:02,498 I'll pass isHighScore a conditional that 80 00:06:02,498 --> 00:06:07,190 checks if the player's score equals the highScores state. 81 00:06:07,190 --> 00:06:11,951 The challenge instructions also states that when the highest score is 0, 82 00:06:11,951 --> 00:06:14,650 all icons should be light gray. 83 00:06:14,650 --> 00:06:21,859 So I'll also add that check by adding and highScore does not equal zero. 84 00:06:21,859 --> 00:06:26,618 We're almost done, we just need to update the memo 85 00:06:26,618 --> 00:06:30,970 comparison function in the file Player.js. 86 00:06:30,970 --> 00:06:35,330 Right now the player component only re-renders if there's a change to 87 00:06:35,330 --> 00:06:37,670 the player score prop. 88 00:06:37,670 --> 00:06:42,890 We need it to re-render when the is high score prop changes as well. 89 00:06:42,890 --> 00:06:45,103 So let's add to the return statement. 90 00:06:45,103 --> 00:06:52,847 And prevProps.isHighScore = nextProps.isHighScore. 91 00:06:52,847 --> 00:06:57,760 Let's see if our highest score features working. 92 00:06:58,810 --> 00:07:04,020 I'll add a score to Guil and the crown has changed from light gray to yellow. 93 00:07:04,020 --> 00:07:07,564 Great. There's likely many ways you can implement 94 00:07:07,564 --> 00:07:09,580 the highest score feature. 95 00:07:10,600 --> 00:07:14,016 I encourage you to experiment with different approaches, and 96 00:07:14,016 --> 00:07:17,830 don't forget to share your solutions with the Treehouse community.