So in the create product action creator which currently is a function that just returns an action,
we can now tweak this a little bit. Instead of returning an action, we can now return another function
in there
thanks to Redux Thunk, thanks to this package we can do this now and this will be a function which receives
the dispatch function as an argument and then in turn needs to dispatch an action. So in here, in this
return function,
I now simply need to not return this but dispatch this action,
that's the important difference and I'm missing a curly brace here.
So what happened?
I change create product to be a function which we actually still can dispatch from inside our components
but which now can still work as before,
so we don't need to change all these action creators, so you can stick to the old syntax but now thanks
to Redux Thunk, an alternative syntax so to say is also supported
where this action creator function does not immediately return an action object but instead, where it
returns a function and if it does, Redux Thunk will step in and make sure that everything still works
and if it returns a function, then this is a function which has to receive an argument, the dispatch function
which will be passed in automatically by Redux Thunk, so Redux Thunk will in the end call this function
for you
and then therefore you can then dispatch a new action and here, dispatch the actual action object which
we previously wanted to dispatch but before you do that,
you can now execute any async code you want and that will be allowed and will not break your Redux flow
because Redux Thunk will take care about this and you can learn more about this in my React Course for
example or of course in the official Redux Thunk documentation,
also in the official Redux docs actually.
So now here we can send a HTTP request and in React Native, we can use the fetch API which is
built-in and fetch here
works basically like the fetch API in the browser where this also is available.
It takes a URL you want to send the request to and that's this URL we got here,
so I'll just copy that URL from Firebase and enter it here.
Now fetch sounds like it always just fetches data,
so if it gets data but actually the name is a bit confusing here, it's not just used for getting data,
you can also use it to send a post request or a put request,
so any kind of HTTP request. Now also we don't just send a request to this URL but now as I
said, Firebase translates your requests to kind of a database query and a database structure, so you
can add any node you want here, any segment you want,
like for example products and Firebase will kind of create a folder here in the database and store your
data in there.
Important and that's just a Firebase specific thing, you need to add .json here.
So that's not required because of React Native or because of Javascript or because it's HTTP request, this
is just a Firebase specific thing. By default,
this would send a get request but to store data Firebase wants a post request and to send that, we have
to pass a second argument to fetch which should be a Javascript object. In that second argument,
you can set up the method key and describe the HTTP method of this request and that can be get,
put and so on and here it should be post which adds this product we're about to send to this node which
will be created there.
Now you also can set up some headers there and we need to set a header,
we need to add the content type header and you simply add headers as an object and then have key-value
pairs with your header identifiers as keys and the values as values
and here the value is application/json to let Firebase know that we're about to send some JSON
data and then we need to do that.
We need to add a body with the data we want to append to this request and the data should be in the JSON
format.
Thankfully, React Native supports the JSON object which browser-side Javascript also supports and there
we can call stringify to turn a Javascript array or object into JSON format, so into a string in the
end and there,
I want to append my product. So in the end, I want to stringify
an object here which holds my title, my description,
my imageUrl and my price,
not the ID because actually Firebase will generate an ID for us here which is really convenient.
Now
this will send the request but of course I only want to create the product locally if that request succeeded
because then I can actually also use that automatically created ID which Firebase will return to
me and fetch conveniently returns a promise, which is this Javascript object that will eventually resolve
to a value in the future or throw an error in the future.
So to wait for this response, we can then add then here after fetch,
so on this promise and we'll get our response here so that we can do anything with the response.
You can also listen to the errors with catch and that's something you should actually already know because
promises are not React Native specific,
that's vanilla Javascript and React Native also supports the more modern async await syntax instead
of then and catch. To use that, you add async here in front of your function,
this async keyword and now you can await your response here and store it in a constant with this syntax,
with the await keyword.
Now behind the scenes, this transforms this to the old syntax with then,
so this is like if you added then here and you used your response in a callback you got there.
But this is a bit easier to read which is why I will use this async await syntax,
just be aware of the fact that this is like adding then, just more readable. When you use async await
by the way, this function here always will automatically return a promise, therefore this entire create
product function
now returns a promise.
It didn't do that before,
now it will,
you see that here, it now returns a promise. So that's our response,
this response now can be kind of unpacked to get the data in there,
so the response data, that's done by calling response.json, that's a method which is available
on that response object we're getting. This again is an async task which we have to await for
and now this will in the end give us the data returned by Firebase when we add a product.
Now we can for now simply log that response data to see what's in there and I still dispatch my action
here
but since we have await here and therefore this is like it was in multiple then blocks, this will only
be dispatched once these operations here are done.
So with that, let's save this and let's add a new product by going to the admin section here and then
I'll add a white shirt,
I picked a nice imageUrl for that,
here it is.
Let's say that costs 39.99, this is a white shirt which is pretty stylish.
If I now save this, need to load this first,
now this is added,
here it is
and now if you have a look at Firebase, we also see that there now is a products node. In there,
this is this unique ID and in there we have the data we submitted
and if you have a look at your console, you see this is what we got back,
that's this response data here.
This holds a name key and then also holds this ID which Firebase generated,
this means that when we dispatch our data here, we can actually add an ID key here and add resData.name
to access this name key on the response return by Firebase to forward the server-side generated
ID to our create product reducer in the end or to the logic that runs in the reducer.
So now in the products reducer, we can actually not use this dummy ID here but instead, expect that
on our product data. There we now get an ID field which is the server-side generated ID, I will stick
to the dummy user ID for now though but we'll get this server-side generated ID here and here it
is and therefore, we use this on the frontend as well which will be important for later when we also
delete stuff and so on.
So this adds a product but of course as soon as we reload the app, it's gone because in the app, it was
only stored in memory.
Now we also store it on a server but we're never fetching it from a server,
so let's make sure we do that as well.