Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
For adding cart items,
we need to go to the CartProvider
because that's where we manage our cart data in the end.
And here we've got this addItemToCartHandler.
Now, whenever this function is called,
we get the item that should be added to the cart.
And then I basically wanna check
if that item is already part of the cart.
So if we, for example, already have sushi in the cart,
and if that's the case, I wanna update the existing item.
If it's not the case, I wanna add a new item.
And of course, we wanna manage this
as state in this component
so that this component and therefore, the context
and therefore, any components affected by the context
are re-evaluated whenever the cart data changes.
So here we wanna import useState or useReducer.
Both are React hooks which allow us to manage state.
And I will go for useReducer here
because this will be a bit of a more complex state,
which we're managing here
because we'll have to check whether a meal
is already part of the cart or not
and for removing, we'll also have more complex logic.
Hence I will use useReducer for managing the state here.
And therefore, as a next step,
outside of this component function,
I'll add my cartReducer function
outside of the component function
because this reducer function won't need anything
from that component.
It won't need any surrounding data
to find in this component.
And it shouldn't be recreated all the time
when the component is reevaluated.
Now, you learned that in the reducer functions,
you receive a state object
and an action automatically by React.
The action is dispatched by you later in your code
and the state is simply the last state snapshot
of the state managed by the reducer.
And then as part of the reducer function,
you have to return a new state snapshot.
Now, for this, I'll define another constant outside
of the component function
and outside of the reducer function
and that's my defaultCartState.
Now, that's simply an object
where I say that I have no items,
so an empty array and a totalAmount of zero therefore.
And then it's this defaultCartState,
which I return here in cartReducer.
Now, with that, in CartProvider
at the very top of this component function,
we can call useReducer, this React hook,
which we're importing
and now as a first argument,
we point at our reducer function here.
We don't execute it, we just point at it.
It will be executed by React for us then.
And we set an initial state
and that's the defaultCartState.
So I'm reusing that constant here.
Now, you learned that useReducer returns an array
with exactly two elements.
Hence we can use array destructuring
to pull these elements out of that array
and store them in separate constants.
The first array element is always your state snapshot.
So I will name it cartState here.
The second element is this function,
which allows you to dispatch an action to the reducer.
So I will name it dispatchCartAction.
Both names are up to you
because it's the position which matters here
in array destructuring.
Now, the cartState is now needed
to construct this cartContext object.
Instead of hard coding the empty array here,
I will access cartState.items
because we're now managing the items with state
and the totalAmount with cartState.totalAmount.
Now we can start dispatching actions
and I wanna start with adding items to the cart.
Here we can then dispatch a cart action
and as I explained when I introduced
the useReducer hook earlier in the course,
it's totally up to you what an action is.
It could just be a number or a text
but typically it's an object,
which has some property,
which allows you to identify that action
inside of your reducer function
so that in that reducer function,
you can run different pieces of code depending
on which action type was dispatched.
And I will use type as a property name
for identifying the action
but it's totally up to you how you name this.
You could also name it identifier
or whatever you want,
but I will go with type
and then follow this convention
of having a string all caps identifier.
Again, it's all just a convention
but a very readable and common one,
which is why I will stick to it.
And then here we have let's say a type of ADD.
It could also be ADD_ITEM or ADD_CART_ITEM
or whatever you want
but I'll keep it simple and short and just use ADD.
Now, to add the item in the reducer function,
I also wanna forward the item as part of the action.
So I will add a second property to this action object
and name it item.
This name is also up to you
and point at my item argument here
so that I'm forwarding the item,
which I expect to get here on this function
to my reducer.
And now we can go to the cartReducer
and start adding logic for adding a cart item here.
For this, I, first of all,
wanna add an if check
and check if the action.type is equal to ADD
because I only wanna run this adding logic
for this kind of action.
At the moment, it is the only action type we have
but later, we'll also have a remove action.
If we want to, we can already dispatch this here,
by the way.
We can already add type: REMOVE here
and forward the id, let's say, like this
in the removeItemFromCartHandler.
Now we would have, theoretically at least,
two kinds of actions,
which trigger this reducer
and therefore, we wanna check
for which type of action it was triggered.
And now in here, I wanna update my cart items.
We could simply add our item as a new item in that array
but as I mentioned, I wanna group items
for the same meal together
and manage the amount on a per meal basis.
I also wanna update the totalAmount,
the total price for all aggregated cart items.
Now, let's start simple and simply add a item
as a item to the array though.
And or this, we can simply create an array.
Maybe name it updatedItems
and set this equal to state.items.
So the items in the current state snapshot,
which we get as a first argument in the reducer by React.
And call concat.
Concat is a built-in method in JavaScript,
which adds a new item to an array
but unlike push, it doesn't edit the existing array
but return a new array.
And that's kind of important.
You wanna update your state in an immutable way,
which simply means you don't wanna edit
your old state snapshot
because of the reference value thing in JavaScript.
That would mean that existing data in memory gets edited
without React knowing about it,
but instead, you wanna generate a brand new state object,
which you return.
And concat gives us a brand new array
instead of editing the old array in memory,
which is better.
And we wanna concat this item.
This action.item to be precise, which we're getting.
And I simply expect to have all the data I need
on that action.item.
So the name, the amounts of items
that should be added, the price,
I expect to have all of that on the item,
which reaches this addItemToCarthandler.
Currently, we're not taking care about this yet
in the other parts of the applications
but we will do so in the future.
Now, with that, we get the updatedItems.
I also wanna get my newTotalAmount
or my updatedTotalAmount
and that should simply be the old totalAmount
on the old state snapshot
plus well, action.item.price
times action.item.amount.
So I expect to have an amount field
on that item which we're getting and a price field.
And of course, if we multiply these two,
we know by how much our totalAmount needs to change.
And with that, we can return our new state.
At the moment, I'm not checking whether our item
is already part of the array by the way.
That's something we'll add in the future.
For the moment, I will simply return a new state snapshot
where I set items equals to updatedItems
and totalAmount equal to updatedTotalAmount.
And now we've got this basic cartReducer finished.
Now we need to make sure as a next step
that addItemToCartHandler
is being called from some components in our application,
like the Meals component where we have all these meal items
and the MealItemForm
with the appropriate data.
So with an amount field on every item,
with a price field on every item,
with a name field on every item,
with an ID field on every item.
That's what I wanna work on next.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.