Now that we can add data to Firebase,
so that we can store data on a server
and that we can fetch data whenever we visit all meetups,
now with that we got the core functionality built in.
The last feature, which I wanna add here
is this favorites feature.
This button here should be clickable
and when we click it, this meetup should
be added to our favorites.
Then on the my favorites page
I wanna see a list of all my favorites
and of course, as soon as item is a favorite
I want to be able to unfavorite it.
And then I also want to show a little badge here
in the navigation next to my favorites
where we see the current count of favorites.
That's the last feature I wanna add.
And for this we'll need to manage some state
which affects more than one component.
Because our list of favorites is some state
that should cause the UI to update
because we, for example, will have that badge here,
which shows the current number of favorites.
And of course this button should change once
our item is a favorite.
So we'll have different parts
of this application that will be affected by our state.
And because that's the case, because we'll have
a state that affects more than one component
we will need a mechanism of managing that state globally
and distributing that state to different components.
Because just using use state inside of a single component
doesn't necessarily do the trick anymore,
because that only affects one component.
Now, one thing we could do is we could lift the state up.
That means that we could, for example
manage our favorites state in app JS,
and then we pass it into all the components
that are interested as props.
So to the layout component which
has access to the main navigation component,
which is where I wanna show this badge in the end,
to that component we could pass the number
of favorites if we manage the favorites state
in the app component, and then to
the favorites page component we could
pass the array of favorite meetups.
So we could manage the state here in the app component
and then just distribute it through props.
That would work, but it has a couple of downsides.
One problem would be that if we have a bigger application
with different States that affect different components
we have to manage more and more state in
this app component, and hence this app component
becomes bigger and bigger and that's maybe not ideal.
Another problem is that if we pass states down through props
that we can end up with very long prop chains.
We pass the number of favorites to the layout component
and from there we pass it into main navigation.
So we already passed props to layout
just so that this component can then
pass that data on to another component.
Whilst that is not horrible
it's also not necessarily great.
And it can also make our code a bit harder to maintain.
And because we have issues like this
there are state management solutions
for managing application wide state
in a more convenient way.
One very popular state management package is Redux.
I cover it in my course, but for many scenarios
we don't even need Redux, because react also has a built
in state management solution for application wide state.
And that's a feature called context.
Now for this to add this context feature,
I'll add a new folder in the source folder
and I'll name it store.
The folder name is up to you
but store is a common convention
since we will set up the state store for this application.
Instead of store, I'll add a favorite stash context JS file
and in this file I'll now create such a context.
For this in this file, we first of all,
import create context from react
so that's a function exposed by the react library
and we can then call create context.
And this that's what the name implies it creates a context.
We don't know yet what exactly such a context is,
but hey, we are creating one at least.
Now context in the end is a JavaScript object.
And we can store this in a constant
and I'll name it favorites context.
I start with a capital F because this object
which is created by context actually
will contain a react component.
And when you build your own react components
the convention which you should follow is that you start
with a capital character for your component names.
So that's why I store my context
in a favorites context constant here.
Now create context also takes an argument
and then the argument is the initial value for that context.
So the initial value for this application
or component wide state.
And that can be any value of your choice.
It could, for example, be an object,
let's say an object where we have a favorites key
which is an empty array initially
because we have no favorites at the beginning
and maybe a total favorites key,
which is zero initially
which is the total number of favorites.
That could be our context
but like this it's not too useful
we also need ways of changing
these values of adding and removing favorites.
And that's why I will also add a component in this file.
So a component function
which I'll name favorites context provider.
This component will be a regular react component
but it will have the job of providing this context
to all the components that are interested
in listening to the values,
So all the components that need values
from the context and this component here
the favorites context provider component
will also be responsible for updating the context values.
Now for this what we'll do here is we'll return
favorites context so this constant
which we created here dot provider,
that's a component this context object has built in.
And this provider component needs to be wrapped
around all the components that are interested
in interacting with that context.
Now, this favorites context provider component
which we are building here itself should be wrapped
around other components later.
I plan on using it in index JS to wrap it
around my entire app so that all the components
in the app have access to the context.
And therefore, what we can do here
is we can accept props and simply wrap
this provider component, which we get
from this context object around props children.
That means that we can now wrap our component here
around any other components.
And those components will be wrapped
by context automatically.
I hope this makes sense.
Now why am I doing it like this?
Because now in his favorites context provider component
which we're building here, we can manage our context data.
We can manage that with state,
because this component which we are working on here
is still a regular react component.
So when we manage state in there,
when we changed that state, that component here
we'll still execute again and we'll be re-evaluated
and that means that if we change our context value
in this component, and we pass
this context value to the provider
all components that are listening
to our context will be updated
and will get that latest updated data.
And in case it's not 100% clear yet
we'll get there step-by-step
because we're now going to add the logic for this.
In favorites context provider I'll create a context object
and I'll pass this context object as a value
to favorites context dot provider, this component
which is exposed by this favorites context object
wants a value prop where we pass the current context value.
We set the initial values here when we create the context
but we can then update those values
and pass the latest values with help of that value prop.
And whenever that value changes
all components that are listening
to our context will be updated in the end.
That's how this works.
So now we just need to derive this context object
and its values dynamically.
And that's where use state comes into play now.
We can manage some state here
in this favorites context provider
and we can manage an array of favorited meetups here.
So here we have the user favorites
let's say and a function for setting those user favorites.
Now here this context object, which we construct
which holds the latest values that should be exposed
to our components, that object now
has a favorites key because we defined
it here in the initial context value as well.
And we set our current user favorites array
this state snapshot as a value.
So when the state changes this value will change
and will have a new context object
and will pass this new updated context object
to all the components that are wrapped
by this provider in the end.
And I'll also set total favorites here
and that is simply user favorites dot length.
Like this, now we just need a way
of changing our state here.