1 00:00:02,250 --> 00:00:07,590 Adding a button to the header as I want it here, such a navigation button, requires a bit of extra work 2 00:00:07,590 --> 00:00:11,670 initially but thereafter is very straightforward. 3 00:00:11,700 --> 00:00:17,160 We have first of all need to install an extra package to make that easier because theoretically, you have 4 00:00:17,160 --> 00:00:18,540 a lot of power here. 5 00:00:18,660 --> 00:00:21,690 You can add such buttons with the help of the navigation options, 6 00:00:21,690 --> 00:00:27,450 so here on the MealDetailScreen, beside setting a header title, you can set headerLeft and headerRight 7 00:00:27,450 --> 00:00:30,330 to add buttons on the left and the right of the title. 8 00:00:30,330 --> 00:00:36,330 Typically you want to use right because the left is reserved for the back button and generally, you can 9 00:00:36,330 --> 00:00:39,310 simply return a jsx element there, 10 00:00:39,450 --> 00:00:47,220 so you can simply set this to text, like favorite, that is something you could do here and actually let me 11 00:00:47,220 --> 00:00:51,870 show this to you and therefore restart the server before we use a package 12 00:00:51,870 --> 00:00:58,890 because whilst you can just add a component here, getting the styling right, the positioning right for 13 00:00:58,950 --> 00:01:05,430 all the different platforms, especially if you're not just using text here but also maybe an icon which 14 00:01:05,430 --> 00:01:11,160 you typically want to have there, that can be really cumbersome and that's why we'll install an extra 15 00:01:11,160 --> 00:01:14,810 package that makes that way easier than it otherwise is. 16 00:01:18,260 --> 00:01:25,510 So let me restart this with npm start, not npm install, npm start and with it running again, 17 00:01:25,850 --> 00:01:34,320 let's reload this here on iOS and let me show you what we have here now that I render a text. 18 00:01:34,520 --> 00:01:35,930 You see this text here, 19 00:01:35,960 --> 00:01:37,180 so this is getting rendered 20 00:01:37,190 --> 00:01:43,010 but as I said, having the right padding, the right alignment, the right style, the right size, 21 00:01:43,010 --> 00:01:47,870 super annoying if you do it all on your own because you're not just doing this for one device but for 22 00:01:47,870 --> 00:01:49,300 many devices. 23 00:01:49,370 --> 00:01:54,320 That's why we'll actually install a special package here which helps us with this. 24 00:01:54,320 --> 00:02:01,250 So quit the process for now, the running dev process and use npm install --save and 25 00:02:01,250 --> 00:02:10,130 install the react-navigation-header-buttons package which is a package that helps you, 26 00:02:10,310 --> 00:02:16,220 surprisingly if you have a look at the name, with setting up some buttons in your header, so in that top 27 00:02:16,280 --> 00:02:24,850 toolbar here. This is a package which then will make it really easy to add such buttons. With that added, 28 00:02:24,850 --> 00:02:30,490 I'll restart my development server with npm start and now I'll create a new helper component myself in 29 00:02:30,490 --> 00:02:37,290 the components folder which I'll name helper, a header button, not helper, header button. There, I'll 30 00:02:37,300 --> 00:02:44,210 import React from React because this will be a normal React component which we create in there and import 31 00:02:44,570 --> 00:02:51,980 something from this new react-navigation-header-buttons package we just installed and that something 32 00:02:51,980 --> 00:03:02,650 which I import is header button. Besides that, let's also import something from @expo/vector-icons 33 00:03:02,680 --> 00:03:08,830 which should be available but just to be super safe, you can definitely also run npm install 34 00:03:08,830 --> 00:03:16,270 --save @expo/vector-icons to install this package as well because you'll need that 35 00:03:19,050 --> 00:03:24,630 and the thing we need to import from that package is ionicons. Of course, you can use any icon set 36 00:03:24,630 --> 00:03:30,270 you want, I covered icons earlier in this course and you're free to use any icon you want in your header 37 00:03:30,270 --> 00:03:35,250 button, I'll just work with ionicons because I use them in the rest of this course as well but 38 00:03:35,460 --> 00:03:40,440 again, you can use any icons you want and of course in the header, you don't have to use icons, you could 39 00:03:40,440 --> 00:03:45,900 use other text as well but typically, you do use icons of course, that's what users typically are used to 40 00:03:45,900 --> 00:03:49,470 from other apps. 41 00:03:49,740 --> 00:03:58,040 In addition, I'll also import colors from constants/Colors and now create my component here and 42 00:03:58,070 --> 00:04:04,850 that's the, let's say, custom header button or just header button, whatever you want to name it but we're 43 00:04:05,030 --> 00:04:09,290 already importing this, so we have to pick a different name here to not have a name clash 44 00:04:09,650 --> 00:04:17,390 and this will receive some props and will return the header button we're getting from this package 45 00:04:17,390 --> 00:04:22,280 which we installed but we'll soon add some extra configuration which is why I'm wrapping this in a separate 46 00:04:22,280 --> 00:04:27,800 component so that we don't have to repeat that configuration for every button we're using anywhere in 47 00:04:27,800 --> 00:04:28,990 the app 48 00:04:29,140 --> 00:04:33,250 and then of course, I'll export my default custom header button. 49 00:04:33,340 --> 00:04:39,850 So now this header button I'm using here from this package we installed, that will first of all receive 50 00:04:39,850 --> 00:04:45,790 all props we're getting with this nice little trick we can use in React where we forward all props 51 00:04:45,790 --> 00:04:51,700 with this shortcut by pulling out all the key-value pairs and passing them to this object which this 52 00:04:51,700 --> 00:04:53,060 component in the end is. 53 00:04:53,110 --> 00:04:56,790 So that's the first thing, we need to forward all the props and that's super important, 54 00:04:56,800 --> 00:04:57,670 don't forget this 55 00:04:57,670 --> 00:05:00,470 otherwise it will not work correctly. 56 00:05:00,490 --> 00:05:07,540 The second step is that we add the Icon component prop with a capital I, 57 00:05:07,540 --> 00:05:13,580 that's a prop the header button we're getting from this package expects and there I pass in ionicons. So 58 00:05:13,580 --> 00:05:20,730 this expects a vector icon package which can be used for rendering icons, doesn't have to be ionicons 59 00:05:20,730 --> 00:05:27,800 but has to be from either @expo/vector-icons or from the underlying React Native vector icons 60 00:05:27,800 --> 00:05:34,850 package on which the expo package is based on and you can also parse in an icon size and I will standardize 61 00:05:34,850 --> 00:05:40,370 this so that all my header buttons across the entire app have the same size of 23 which I found 62 00:05:40,370 --> 00:05:48,470 to work quite well. Last but not least, I'll also set up a color here and I'll use my primary color, though 63 00:05:49,160 --> 00:05:59,360 of course we have to make sure that we differentiate by platform. So I'll also import platform from React 64 00:05:59,390 --> 00:06:06,210 Native because on Android, our header will have the primary color as a background, so there we want 65 00:06:06,210 --> 00:06:08,000 to use an icon color of white. 66 00:06:08,150 --> 00:06:15,320 So here, I'll check platform.os, if that's equal to Android, then I want to use white here and only if it's 67 00:06:15,360 --> 00:06:18,350 iOS, I want to use the primary color. 68 00:06:18,470 --> 00:06:21,020 So now we have that preconfigured header button, 69 00:06:21,020 --> 00:06:26,840 now we can use that in the place, in the component where we want to add it to our header and that's the 70 00:06:26,840 --> 00:06:31,030 MealDetailScreen in this case. There, 71 00:06:31,120 --> 00:06:34,520 we now need to import something else from the newly installed package, 72 00:06:34,720 --> 00:06:41,140 so from react-navigation-header-buttons, from this package, here we have to install or import header buttons, 73 00:06:41,140 --> 00:06:47,710 so not header button which we use in the other file but header buttons, plural. We add this here 74 00:06:47,770 --> 00:06:53,650 because now down there where we set up the navigation options for this component, instead of using our 75 00:06:53,650 --> 00:06:58,200 text component there, I want to use header buttons, 76 00:06:58,250 --> 00:07:04,940 this component I just added the import for and wrap this around another element 77 00:07:04,960 --> 00:07:11,940 we have to import from react-navigation-header-buttons and that's item. Item is another component we import 78 00:07:12,090 --> 00:07:16,710 which we can now use between the opening and closing tags of the header buttons, 79 00:07:16,710 --> 00:07:26,600 so here we add item and item is a self closing component where we describe the icon we want to render 80 00:07:26,600 --> 00:07:31,970 in the end. We can also give this a title which would be rendered as a fallback and I'll name this favorite 81 00:07:32,000 --> 00:07:35,170 but we normally won't see this, instead here 82 00:07:35,180 --> 00:07:37,670 I can also set up an icon name and now 83 00:07:37,670 --> 00:07:46,280 this should be, for example ios-star which is a valid ionicons icon and you can search that 84 00:07:46,280 --> 00:07:51,440 @expo/vector-icons list I showed you earlier in the course which you also find attached to this video for 85 00:07:51,440 --> 00:07:53,570 possible icons you can use here. 86 00:07:53,570 --> 00:07:59,540 Just make sure that you use an icon from the icon set you used in your header buttons, so in my case, from 87 00:07:59,540 --> 00:08:01,990 ionicons. 88 00:08:02,000 --> 00:08:03,830 Now this indicates which icon to use, 89 00:08:03,830 --> 00:08:09,680 now here we can also add onPress to register a function that should be triggered when that icon is 90 00:08:09,680 --> 00:08:12,570 pressed or when that item in the header is pressed 91 00:08:12,650 --> 00:08:19,220 and for now I'll just say mark as favourite here, log this in the console so that we see that this worked. 92 00:08:19,220 --> 00:08:22,720 We're not entirely there yet because we're not using our custom header button, 93 00:08:22,730 --> 00:08:25,870 that's the last missing piece. 94 00:08:26,000 --> 00:08:28,370 We need to import this component we created, 95 00:08:28,430 --> 00:08:35,120 so import header button from components and then there, from header button, that's the button we worked 96 00:08:35,120 --> 00:08:42,740 on and we pass this to header buttons here because this expects a header button component prop where 97 00:08:42,740 --> 00:08:47,870 we point at the component that should be used to render this item in the end. 98 00:08:47,870 --> 00:08:52,220 Now this is all very complex as you can tell, a lot of nested components, 99 00:08:52,220 --> 00:08:57,500 this is just a setup which is a little bit cumbersome the first time you do it but when you then use 100 00:08:57,500 --> 00:09:01,790 it in other components, it's really just all about copying the same setup here, 101 00:09:01,790 --> 00:09:05,860 changing the title, changing the icon and changing the logic and you're there, 102 00:09:05,870 --> 00:09:07,970 so that's all you have to do in the future, 103 00:09:08,000 --> 00:09:12,740 it's just initial setup that's some extra work here. With all that setup 104 00:09:12,740 --> 00:09:14,540 however, if we now save this, 105 00:09:19,710 --> 00:09:25,770 we should be able to see our star here. This is the icon we see and we can press this and as I press 106 00:09:25,770 --> 00:09:35,290 this, you'll see mark as favourite is getting logged here in the console. Let's also see that on Android, there 107 00:09:35,300 --> 00:09:40,150 we always have the star and if I press this star here, we also see mark as favourite, 108 00:09:40,160 --> 00:09:47,100 so that's working. A little side note I just saw if we have multiple recipes, we might want some extra styling 109 00:09:47,100 --> 00:09:52,470 there, totally unrelated to the header button, just seeing it. So in the MealItem.js file, on the meal 110 00:09:52,470 --> 00:09:56,460 item, I'll actually add some margin vertical of 10, again, 111 00:09:56,520 --> 00:10:02,520 totally not something you need here, just there to make sure that this looks nicer if we have multiple 112 00:10:02,520 --> 00:10:03,050 items. 113 00:10:03,060 --> 00:10:08,670 Important thing here of course is that we have our header button, this icon and this is how you can add 114 00:10:09,180 --> 00:10:13,100 buttons or icons items here to your header 115 00:10:13,170 --> 00:10:18,570 and of course, you can add more than one. Here in the meal detail screen, you can have multiple such 116 00:10:18,600 --> 00:10:24,770 items between the header buttons here which you set up on headerRight on the navigation options. 117 00:10:24,850 --> 00:10:26,220 This is how you add items here, 118 00:10:26,220 --> 00:10:33,750 you can have more than one, for example here we could also have ios-star-outline which is another icon 119 00:10:33,750 --> 00:10:37,260 which looks a bit different so that we can see the difference here, 120 00:10:37,260 --> 00:10:38,630 now we have two here. 121 00:10:38,790 --> 00:10:45,600 So that's possible, of course you shouldn't overload this so that your UI stays clean and just works 122 00:10:46,710 --> 00:10:55,010 but this is how you can add icons here to your screen. By the way, the warning I'm getting here regarding 123 00:10:55,010 --> 00:10:59,910 the double keys, the title here is also used as a key for your items, 124 00:10:59,930 --> 00:11:03,350 so if you have multiple items, you shouldn't use the same title 125 00:11:03,350 --> 00:11:08,640 but I just added this for demonstration purposes anyways, so I'll simply get rid of it and we're good. 126 00:11:08,810 --> 00:11:12,290 Now our star icon doesn't do anything yet, 127 00:11:12,320 --> 00:11:17,660 that's something we'll add later but at least we see it and that's really important in a module where 128 00:11:17,660 --> 00:11:20,300 we talk about navigation and working with the header.