So I cleared firebase,
now we can work on the orders page which of course is empty right now.
So first of all with everything fixed, let's place a new order for our standard burger here,
let's enter some contact data into the field, test street, some zip code, country and an e-mail address,
let's place that order
and on the orders page, we do see it,
it's just that if we have a look at the orders container, we're not really using redux for that, here
we're reaching out to the web in componentDidMount. Of course I want to fetch my orders through an action
creator and I want to manage my orders through redux,
we already created that orders array in our state there,
we're just not using it.
So let's start with the action creator and for that I'll start with the action types, I'll export new
constants here and I'll name it FETCH_ORDERS_INIT maybe so that we have a similar pattern as for the
purchase where we can set loading to true and then trigger this starting process where we reach out to
the web and then we have the success case and so on.
So FETCH_ORDERS_INIT, fetch orders
let's name it start, let's name it start because we also name that PURCHASE_BURGER_START,
so start and then we have a constant FETCH_ORDERS_SUCCESS and of course use the same name as the string
identifier
and then finally a third constant I'll need, FETCH_ORDERS_FAIL and you guessed it, we'll use this name as
a string identifier too. With that, we get the action types,
now in my order.js file in the actions folder, I want to create the action creators, so I'll create
a couple of new constants which hold functions and there, I'll use a similar pattern
as for purchasing burgers where we also had success, fail and start and purchase burger itself which is
dispatched from a container which does the async code part.
So we'll have a fetch orders
success function where I do expect to get the orders as an argument so that in there, I can return a
new object where the type,
so that is our action of course, where the type is actionTypes.FETCH_ORDERS_SUCCESS and pass the orders
as a payload,
now I also want to create a new constant FETCH_ORDERS_FAIL, like this where I get a potential error
we receive and I return a javascript object where I set the type to, whoops,
where I set the type to actionTypes.FETCH_ORDERS_FAIL and pass on the error in case I want to
use it.
And I want to have an exported constant which I'll name fetchOrdersStart, there
I don't expect any argument,
what I want to do there though is I want to return a javascript object of course, our action where the
type is actionTypes fetch order, fetch orders not success but start and this again has a similar pattern
as for purchasing, PURCHASE_BURGER_START and then I need my constant here where I run my async code.
So the last action creator is just fetch orders, there I expect no argument either but in there, I will
now use axios to get my orders
and we already got the code in the orders file, here in componentDidMount,
I can actually copy that code here.
Here we also already used the error handlers, so that's good.
I can copy that code from there, put it into my action creator though here of course I need to return
a function which gets dispatch first,
that is what we return
and in there, we're now reaching out to axios and we get it from orders.json
here, use our axios instance of course. We won't call set state though,
instead I here want to dispatch my other actions so dispatch fetch orders success here in the then block
and there, I want to pass my fetched orders which I do transform here as an argument and that is a good
argument for where do we transform data.
I do it here because I'm transforming the data I'm getting back, I don't want to put this into the reducer
because if I ever change my backend data, I would have to change my reducer and in this case, I have
to change my action creator I guess,
but still it feels more natural for me to have a reducer where I get the data in the format I want
to store it,
where I only want to do logical changes and don't want to change anything just because of the data format I get.
That is why I do data format changes like this in my action creators.
So the fetched orders are then passed onto the FETCH_ORDER_SUCCESS
handler, I don't need to pass on loading here because I can set this right in my redux state and then
here, in catch I want to dispatch fetchOrdersFail and execute this of course and I want to pass on my
error.
So with that, we're handling this,
now of course the next step is to handle all these new action types in the reducer too.
So let's head over to the order reducer and there, I now want to add a couple of new cases in front of
the default case.
The first one is actionTypes.FETCH_ORDERS_START, in there.
I obviously will return an updated state where I copy the old state and there, I also want to set loading
to true,
it's the same loading property we use in the checkout page but we're only either on the checkout page
or the orders page,
so it's fine if we reuse the property on both pages.
That's the only thing I want to do here in action,
the next action type is success case so that we have FETCH_ORDERS_SUCCESS, here of course,
I want to store the orders I fetched so I'll get my state and I'll set orders equal to action and
there the property name was just orders,
we can confirm this in our action creator, in the order file, there we dispatched fetchOrderSuccess
and in fetchOrdersSuccess,
we have our orders property. So this is the orders property we can extract in our reducer therefore, this
one
and these are the orders already,
if you have a look at the transformation function in an array format, so we can store that in our array.
And the final thing I want to add to this update here is that I of course need to set loading to false
and now I of course need another case action types fail so FETCH_ORDER_FAIL.
There I'll also return a javascript object where I copy the state and we could handle the error,
we could store the error in our arrow property here but I don't want to use it here,
I'll do simply the following,
I'll set loading to false here too because even though it failed, the loading at least is done.
So that's the updated reducer,
we updated our order action creator file,
now I just need to export the fetch orders action in the index.js file here
in the actions folder so that we can trigger this from outside.
And with that we can connect our application,
so let's do that now in the orders component here in the orders container. There in componentDidMount,
I want to dispatch this new fetch orders action we just created and for this, I of course need to
create my new mapDispatchToProps constant where I receive the dispatch action or method and then
can return a map,
so a javascript object here where I do map my props to dispatchable functions,
so I name this onLoad or maybe onFetchOrders to be in line with the action names and there, I want
to execute an anonymous function where I eventually dispatch the action we just created it
which I therefore need to import. So I import everything as actions from
and now let's move on to the store folder,
the actions folder and the index.js file in there.
Again we could omit the index part here due to the way our workflow works
and with that added, I want to dispatch one action from the actions object we import, the fetch orders
action and we need to execute this function to really get the action,
keep in mind, these are action creators.
Now with that added, we can call onFetchOrders in our componentDidMount hook, this.props on fetch orders
executed but of course for this to work, we need to connect this constant here with our component.
So I should import connect from react-redux,
so import the connect function like this from react-redux, like that.
And then as we did in the other components too, let's add connect, execute it and pass for now null instead
of
mapStateToProps and mapDispatchToProps, the second function and let's then also wrap withErrorHandler
and its function call with parentheses.
Now this should work,
I'm of course also interested in the state though because I need my orders,
right now we manage orders and loading in the internal state,
let's get rid of that
we don't do that,
we use redux instead.
So let's add a second constant, mapStateToProps, I get the state here and I return a javascript object
where I do map slices of the state to props and there, I'm interested in my orders which I get from state
order orders. With state order, I'm reaching out to the order reducer and with orders,
I then reach out to the orders property in the state of that reducer and the other piece is the loading
state, here that is loading, that is state order loading. And now with that, I can pass mapStateToProps
to my connect function too and then we can use our orders.
So here, we don't use this.state.orders but this.props.orders, just like that
and if we wanted to show a spinner, we would have to import it, so we can import spinner from
and now let's reach out to our components, to the UI components and to the spinner there.
And let's use this loading state, I'll create a new variable loading, excuse me orders and this should be my
spinner initially but then I'll add an if check,
if this props loading,
if this is not true, so if we are not loading, I'll render this instead, this map. So then orders should be this jsx
code here
and since it's not wrapped in any html element, we can just write it like this.
Now down there, I can safely output orders and I should get rid of this curly brace here.
So with that, if I go back to my application and I reload the orders page, I get my orders but I never see
the spinner,
the reason for this is that in our order action creator file in fetch orders, we never dispatch fetch
orders start,
I need to do that of course to set loading to true.
So right at the start, I'll dispatch fetchOrdersStart, execute it.
Now if we save this, we see well it's so fast, firebase is too fast but we see the spinner for a fraction
of a second and we can confirm that fetchOrdersStart was accessed here.
So with that, we're now fetching the orders through redux, we're managing them in our store and we do manage
them both when we place an order and when we visit the orders page. Side note, since we always load orders
when loading the order container, it doesn't really matter that we also store an order on a successful
purchase. In the order reducer, purchaseBurgerSuccess where I store this new order,
that doesn't really matter because we load orders from the server anyways when you visit the order page.
But we can confirm in our redux dev tools that we do store it before we fetch it from there
and it's of course nice to know how we could store a new order programmatically without reaching out
to the server in case we needed that on some other page too.
So with that, the orders page is also working. Let's now have a look at our application and see if everything
works before we have a look at what we can improve.