We'll continue working on the app we built in the last course module with our recipes here and with
the filters we could set and so on and there are two things we need to add where we will need Redux.
One is that we actually can mark a recipe as a favorite by clicking that star icon, that this actually
marks this as a favorite and that we for one also change this icon to show whether that already is a
favorite or not
but then more importantly, that we can see that recipe as a favorite here in the favorites tab. And the
other thing where we will need Redux is here in the filters, there when we set a filter and we then
save this, of course this should have an effect on the meals we're loading here in our meals tab in the
list of meals when we select a category. There
this should be reflected, what we set on the filters. So that is what we work on, what we'll need Redux
for and for that, let's install Redux and let's get started with it.
To get started with Redux, I'll quit my expo server here,
the npm start process, I'll quit it temporarily and install a package
and that would be Redux
and in addition to Redux, we also need to install React Redux because that's also required to then
work with Redux.
So both packages need to be installed here and whilst they are installing, we can already get started
working on our code files there a little bit because in this project, I want to add a new folder now
and it's the store folder.
Now you can name this folder whatever you want, it doesn't have to be named store, Redux doesn't care
but this is the folder where I want to manage my Redux setup in because Redux is all about that central
state store.
So here in that store folder, we can now get started with Redux and I won't cover Redux in the greatest
detail here,
I have a complete React and Redux course for that if you want to learn the ins and outs of that, for this course
I actually assume prior React and Redux knowledge and therefore this will only be a brief refresher.
Redux in the end is all about reducers, actions and then building a store based on these reducers
and actions.
Now for that here in that store folder, I'll add an actions folder and I'll add a reducers folder, actually
we'll only have one action and one reducer file in this project but if you had more files than that, having
separate subfolders might be a good idea to keep it organized and that's why I create them here, even
though for this simple app, we wouldn't need that because we won't have that many files.
Let's get started with the reducer. In the reducer folder here,
I'll add my meals.js file and that's the file where I went to manage my meals reducer state updating
logic.
So that's in the end the file where we will write the logic for marking a meal as a favorite and for
managing our filters.
Now a reducer in React is just a function,
So here I will create a function, name it meals reducer, name is totally up to you and this function
will actually receive two arguments - the state, the current state snapshot on which you can build up on
and derive a new state because a reducer in the end will have to return a new state which is then
taken by Redux and stored in its store.
So you get the current, the old state here and you get the action because the reducer function here
is executed by Redux
whenever a new action is dispatched and therefore we get access to the action here so that we can find
out if we need to act and what we need to do.
So inside of this function, in the end then you need to return a new state, in its simplest form
that of course means we return the current state which on the other hand means that this reducer doesn't
do anything useful but we'll change that.
Now when we first execute our app, we also want to set up an initial state which is used initially, so
which initializes our state
when this app launches and for this, I'll add a new initial state constant here which holds a simple
Javascript object and in there, I want to store a list of my meals and then also a list of my filtered
meals because we'll need both - a list of all meals and a list of the meals that fit the filters the user
set and I also want to have my favorite meals here. So three types of meal arrays which I store in
the end
and of course that's just one possible approach you could take here,
we can certainly find other ways of managing our data here but I like this one.
Now what I'll need in this file is my meals dummy data, so I'll import meals from my data folder and
there from the dummy-data.js file and I'll initialize meals here with my meals dummy data array.
Filtered meals also is initialized with that because initially when this app starts, we have no filters
setup. Favorite meals on the other hand initially is an empty array because again when the app starts, we'll
have no favorite meals.
Of course in a real app, you might want to store that state on a server, so that when the user closes
the app and comes back later, you don't start from scratch again
but that's not something we'll do here,
you'll learn how to reach out to a server and save data there and load data from there in separate modules
later in this course,
here we'll keep this simple to focus on Redux.
So this is my initial state, here in this function we can now use a Javascript syntax where we assign
our initial state as a default value for the state argument, which means that when this reducer function
runs and state is undefined which is the case when Redux executes our reducer for the very first time,
we'll get started with that initial state,
so that will then automatically load our initial state
so to say because when Redux gets started and starts up, there will be one initial action dispatched
which is used to run through the reducer once and that will then load our initial state.
So with that, we can work with some initial state which is nice but which on its own doesn't help us
too much. For the moment,
that is it though,
let's now connect this reducer to Redux such that we can actually use our Redux store everywhere in
the app before we then start dispatching actions and do more useful stuff in the reducer. Hence here
for now, I will just export the meals reducer as a default here and now in app.js which is the
file where our entire app starts,
we need to setup our Redux store. For that in here,
we import create store from Redux.
In addition, we'll need to import combine reducers from there.
This allows us to now create a store, we'll just need our reducer,
so here I'll import my meals reducer from and now point at the store folder,
the reducers folder and there, the meals.js
file and now maybe here, we can create our store here by calling create store. Now create store takes
a reducer in the end which you need to pass in. Now of course here, we have a reducer and we could pass this
in but in bigger apps, you might have more than one reducer because you often have reducers for the
different feature areas of your app, one for authentication, one for your products, one for let's say the
support area of your app and you need to merge all these single reducers, these different reducers
into one root reducer and that's what the combined reducers function does,
again here we wouldn't need it because we only have one reducer but to already show you the approach
you could use with multiple reducers as well,
I will use it here as well. So I will have my root reducer here which I create by calling combine reducers,
combined reducers takes a Javascript object where we now map our single reducers, our different
reducers to keys.
So for example here, we could take meals as a key but that name is totally up to you and connect this
to the meals reducer, like this.
What this does is it in the end merges this meal reducer into this root reducer and we'll later be
able to work with the state managed by the meals reducer,
so with this state which is initialized like this, with the help of this meals property, we'll be able
to access this state,
this slice of the state with this property later but you'll see all of that.
So that's our root reducer and now we just have to pass the root reducer to create store,
this gives us a store and now what?
Now this store needs to be provided to our application and for that, we need that
other package which we installed which is React Redux.
From there, we can import the provider component, provider like this. We then wrap provider around our
root app component in the end, so around the topmost component which holds all other components that will
eventually interact with our store and the meals navigator is pretty good for that because that holds
all our screens, so it holds all components that we'll eventually need to dispatch actions or access our
state,
so read from our state. Hence here we wrap the provider component around the meals navigator and now
provider takes one important property, one prop which you have to pass and that's the store prop
and of course there, as a value we pass our store here.
So this constant store which holds the created store is passed to the store prop provider and behind
the scenes, this gives us everything we need to now interact with Redux, with the Redux store in any component,
any screen or any other component in our application.
Now let me restart this with npm start and for the moment, this won't make a big difference but our app
should certainly still work, so it shouldn't crash because of that, so
let's just verify that this is the case and let's reload here, we're pressing r twice on Android and command
r on iOS and let's see where that still loads as it should, yes that's looking good here on iOS and
I'm pretty confident that it will also load just fine on Android, yes that's working too.
So now Redux is set up,
our store is initialized but we're not using it.
So as a next step, let's make sure we use our store before we then take care about actions and doing
some real work in the reducer.