Adding a button to the header as I want it here, such a navigation button, requires a bit of extra work
initially but thereafter is very straightforward.
We have first of all need to install an extra package to make that easier because theoretically, you have
a lot of power here.
You can add such buttons with the help of the navigation options,
so here on the MealDetailScreen, beside setting a header title, you can set headerLeft and headerRight
to add buttons on the left and the right of the title.
Typically you want to use right because the left is reserved for the back button and generally, you can
simply return a jsx element there,
so you can simply set this to text, like favorite, that is something you could do here and actually let me
show this to you and therefore restart the server before we use a package
because whilst you can just add a component here, getting the styling right, the positioning right for
all the different platforms, especially if you're not just using text here but also maybe an icon which
you typically want to have there, that can be really cumbersome and that's why we'll install an extra
package that makes that way easier than it otherwise is.
So let me restart this with npm start, not npm install, npm start and with it running again,
let's reload this here on iOS and let me show you what we have here now that I render a text.
You see this text here,
so this is getting rendered
but as I said, having the right padding, the right alignment, the right style, the right size,
super annoying if you do it all on your own because you're not just doing this for one device but for
many devices.
That's why we'll actually install a special package here which helps us with this.
So quit the process for now, the running dev process and use npm install --save and
install the react-navigation-header-buttons package which is a package that helps you,
surprisingly if you have a look at the name, with setting up some buttons in your header, so in that top
toolbar here. This is a package which then will make it really easy to add such buttons. With that added,
I'll restart my development server with npm start and now I'll create a new helper component myself in
the components folder which I'll name helper, a header button, not helper, header button. There, I'll
import React from React because this will be a normal React component which we create in there and import
something from this new react-navigation-header-buttons package we just installed and that something
which I import is header button. Besides that, let's also import something from @expo/vector-icons
which should be available but just to be super safe, you can definitely also run npm install
--save @expo/vector-icons to install this package as well because you'll need that
and the thing we need to import from that package is ionicons. Of course, you can use any icon set
you want, I covered icons earlier in this course and you're free to use any icon you want in your header
button, I'll just work with ionicons because I use them in the rest of this course as well but
again, you can use any icons you want and of course in the header, you don't have to use icons, you could
use other text as well but typically, you do use icons of course, that's what users typically are used to
from other apps.
In addition, I'll also import colors from constants/Colors and now create my component here and
that's the, let's say, custom header button or just header button, whatever you want to name it but we're
already importing this, so we have to pick a different name here to not have a name clash
and this will receive some props and will return the header button we're getting from this package
which we installed but we'll soon add some extra configuration which is why I'm wrapping this in a separate
component so that we don't have to repeat that configuration for every button we're using anywhere in
the app
and then of course, I'll export my default custom header button.
So now this header button I'm using here from this package we installed, that will first of all receive
all props we're getting with this nice little trick we can use in React where we forward all props
with this shortcut by pulling out all the key-value pairs and passing them to this object which this
component in the end is.
So that's the first thing, we need to forward all the props and that's super important,
don't forget this
otherwise it will not work correctly.
The second step is that we add the Icon component prop with a capital I,
that's a prop the header button we're getting from this package expects and there I pass in ionicons. So
this expects a vector icon package which can be used for rendering icons, doesn't have to be ionicons
but has to be from either @expo/vector-icons or from the underlying React Native vector icons
package on which the expo package is based on and you can also parse in an icon size and I will standardize
this so that all my header buttons across the entire app have the same size of 23 which I found
to work quite well. Last but not least, I'll also set up a color here and I'll use my primary color, though
of course we have to make sure that we differentiate by platform. So I'll also import platform from React
Native because on Android, our header will have the primary color as a background, so there we want
to use an icon color of white.
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
iOS, I want to use the primary color.
So now we have that preconfigured header button,
now we can use that in the place, in the component where we want to add it to our header and that's the
MealDetailScreen in this case. There,
we now need to import something else from the newly installed package,
so from react-navigation-header-buttons, from this package, here we have to install or import header buttons,
so not header button which we use in the other file but header buttons, plural. We add this here
because now down there where we set up the navigation options for this component, instead of using our
text component there, I want to use header buttons,
this component I just added the import for and wrap this around another element
we have to import from react-navigation-header-buttons and that's item. Item is another component we import
which we can now use between the opening and closing tags of the header buttons,
so here we add item and item is a self closing component where we describe the icon we want to render
in the end. We can also give this a title which would be rendered as a fallback and I'll name this favorite
but we normally won't see this, instead here
I can also set up an icon name and now
this should be, for example ios-star which is a valid ionicons icon and you can search that
@expo/vector-icons list I showed you earlier in the course which you also find attached to this video for
possible icons you can use here.
Just make sure that you use an icon from the icon set you used in your header buttons, so in my case, from
ionicons.
Now this indicates which icon to use,
now here we can also add onPress to register a function that should be triggered when that icon is
pressed or when that item in the header is pressed
and for now I'll just say mark as favourite here, log this in the console so that we see that this worked.
We're not entirely there yet because we're not using our custom header button,
that's the last missing piece.
We need to import this component we created,
so import header button from components and then there, from header button, that's the button we worked
on and we pass this to header buttons here because this expects a header button component prop where
we point at the component that should be used to render this item in the end.
Now this is all very complex as you can tell, a lot of nested components,
this is just a setup which is a little bit cumbersome the first time you do it but when you then use
it in other components, it's really just all about copying the same setup here,
changing the title, changing the icon and changing the logic and you're there,
so that's all you have to do in the future,
it's just initial setup that's some extra work here. With all that setup
however, if we now save this,
we should be able to see our star here. This is the icon we see and we can press this and as I press
this, you'll see mark as favourite is getting logged here in the console. Let's also see that on Android, there
we always have the star and if I press this star here, we also see mark as favourite,
so that's working. A little side note I just saw if we have multiple recipes, we might want some extra styling
there, totally unrelated to the header button, just seeing it. So in the MealItem.js file, on the meal
item, I'll actually add some margin vertical of 10, again,
totally not something you need here, just there to make sure that this looks nicer if we have multiple
items.
Important thing here of course is that we have our header button, this icon and this is how you can add
buttons or icons items here to your header
and of course, you can add more than one. Here in the meal detail screen, you can have multiple such
items between the header buttons here which you set up on headerRight on the navigation options.
This is how you add items here,
you can have more than one, for example here we could also have ios-star-outline which is another icon
which looks a bit different so that we can see the difference here,
now we have two here.
So that's possible, of course you shouldn't overload this so that your UI stays clean and just works
but this is how you can add icons here to your screen. By the way, the warning I'm getting here regarding
the double keys, the title here is also used as a key for your items,
so if you have multiple items, you shouldn't use the same title
but I just added this for demonstration purposes anyways, so I'll simply get rid of it and we're good.
Now our star icon doesn't do anything yet,
that's something we'll add later but at least we see it and that's really important in a module where
we talk about navigation and working with the header.