All language subtitles for 009 Using the useReducer() Hook_en

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranรฎ)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

So with that, we know

when we might wanna use useReducer,

how does it work though?

It looks like this, and that's quite a bit of code.

So let's have a look at this step by step.

useReducer just like useState,

always returns an array with exactly two values.

And therefore you can use array destructuring

as we did it with useState to pull out these values

and store them in separate constants.

Now, the two values you are getting

are the latest state snapshot,

because it is a state management mechanism

like useState.

So of course you get your state snapshot.

But you also get a function

that allows you to update that state snapshot.

So that's kind of the same as for useState,

though the state updating function will work differently.

Instead of just setting a new state value,

you will dispatch an action.

And that action will be consumed by the first argument

you pass to useReducer a so-called reducer function.

So this is a function

which gets the latest state snapshot automatically

because this function will be called by React

and it gets the action that was dispatched.

Because React will call this reducer function

whenever a new action is dispatched.

So then it gets the last state snapshot managed by React.

And that gets the action that was dispatched

that triggered this reducer function execution.

Now the reducer function

then also should do one important thing.

It should return a new updated state.

So it's a bit like the function form of the useState hook,

but an extended version of that, you could say,

because of that action thing, which you'll see in action,

no pun intended, in a second.

In addition, you can also set some initial state

and also an initial function

that should run to set the initial state

in case your initial state is a bit more complex.

And for example, the result of let's say HTTP requests

or anything like that.

We'll ignore that for now.

So that's useReducer in theory.

Let's see it in action.

Now I did mention that we could use useReducer here

to combine our entered values and validities

for the email and the password.

And we could also use it to manage

the overall form state with it.

So we could either manage one big form state

that includes everything or in multiple smaller states.

Both would work, both would be fine,

but to keep things simple here,

we will simply start by managing our emailState

with useReducer.

And desired goal is to combine the value

and the validity into one state managed by useReducer.

First of all, we need to import useReducer here.

And we then call it for example here.

And useReducer, as you learned returns an array

with exactly two elements,

and we can use array destructuring

to pull those elements out of it.

Now I'm going to useReducer for my email

and my password separately.

You could also merge this all into one big reducer

and here we therefore get back,

let's say the emailState and our dispatch function.

I'll name it, dispatchEmail.

These names are up to you, of course.

Then I mentioned that useReducer as a first argument

takes a function.

Here again, I'm using an anonymous function.

Though we actually could also outsource this

into a separate named function,

maybe to make this easier to read.

And I'll name this emailReducer

and I'll store my function,

my arrow function in this constant

so that I can point at email reducer here.

Now, please note that I created this reducer function

outside of the component function.

And I did so because inside of this reducer function,

we won't need any data

that's generated inside of the component function.

So this reducer function can be created outside of the scope

of this component function

because it doesn't need to interact with anything

defined inside of the component function.

All the data which will be required

and used inside of the reducer function

will be passed into this function

when it's executed by React, automatically.

So that's why we can define it

outside off the component function here.

Now this reducer function receives two arguments,

two parameters.

Our last state snapshot and the action that was dispatched.

And you'll see what this action is in just a second.

And we should return a new state.

Now here, our state could be an object

where we have the value, which is initially an empty string.

And let's say the isValid field, which initially is false,

for example.

That also could be our initial state here

which is the second argument

we passed to useReducer value and isValid to false.

That's the initial state we set here

for our emailState snapshot.

Now the emailState is therefore what we can use in our code.

For example here, where I want the entered email.

Now that's emailState.value

because that's where we're going to store it.

The entered value.

We don't have to code for that yet, but soon we will.

So that's where we could access this.

Also here, emailState.value.includes('@').

But actually keep in mind

that we have the isValid field in there

and we're going to add code that changes it eventually soon.

So instead of revalidating here,

we could also just check if emailState isValid is true,

and therefore we can simplify this here,

emailState isValid.

And if we scroll down further here in the submit handler,

here we wanna forward the value.

So that would be emailState.value.

And then the JSX code, of course,

instead of email isValid,

we have emailState isValid.

And here where I pass the value back into the input,

we have emailState.value,

and that should be the different places

where I'm using my email states.

With that, entered email and email isValid

should now be gray because we're not using them

anywhere in our code anymore.

So we can remove these to useState calls here,

and I will comment them out

so that we still see this alternative,

but we're not using it anymore.

But we're not done with the reducer.

Right now, it always returns to this state,

which of course is not what we want.

Instead, we need to dispatch an action eventually.

We need to dispatch it here, for example,

when we want to update the value,

or here, when we want to update the validity.

Now let's start with the value.

Here we now update this by calling dispatchEmail

and we pass to it as so-called action.

Now it's totally up to you

what this action is.

It can be a string identifier,

something like NEW_EMAIL_VALUE.

It could be a number,

but often will be an object

which has some field that holds some identifier

often the field is then named type.

And that could be something like USER_INPUT, for example.

Now it doesn't have to be all caps.

That's just a convention you see a lot.

So a string, all caps,

with some clearly understandable identifier.

And then we also can add an extra payload to this action.

Again, I'm saying you can, because it's up to you,

but here, since we wanna save what the user entered,

it would make sense to add some payload.

So for example, a val field

that holds the event target value.

So now that's our action.

It's this object with a type field

that describes what happened and extra payload in this case,

the value the user entered.

So this now will trigger this function here to execute

because that's the reducer function we passed to useReducer.

Now here we can handle this action,

for example, with the if statement.

We can check if action.type is equal to user input.

Keep in mind, what we dispatch as action will be an object

because that's what we set it to here.

And this object happens to have a type field

so I can check for action.type here

and check if the values stored in that type field

is that string with the content user input.

And if that's the case, we could say,

now then I don't want to return this empty state snapshot.

Instead, I want to return the state snapshot for my email,

where the value is action.val.

That's the payload we appended to our action.

And maybe we also want to update the validity here,

if we're already added.

Simply by, for example, checking if action valid,

and then the same logic as down there,

includes the @ symbol for this very trivial validation.

So here I'm then updating both the value

and isValid whenever I received as user input action.

And for any other action that might reach this reducer,

this default state will be returned.

Now we also need to dispatch an action here

on the validate email handler.

So instead of setting the email as valid here,

I can dispatch,

email again.

Again, passing an object.

You should be consistent.

Your actions should always have the same structure,

so that your code, where you,

for example, try to access a type property

does not suddenly fail.

So once you've decided for an action structure,

you wanna stick to it.

Therefore, here I, again, dispatch an object

with a type field.

Now here it's for example,

input blur, because the input lost focus,

it was blurred.

And we don't need to add a value here necessarily

because all we care about here

is that the input lost focus.

There is no extra data that needs to be added.

So here we have a simpler action.

So still an object, still with a type property,

but without a value.

The fact that the val is missing does not matter

because this line here,

where we try to access the value,

will not run for action of type input blur.

Because we only run this if the action type is user input.

Instead I will check if the action type is input blur.

And if it is, I wanna return a new snapshot,

a new state value for my emailState.

But now the value of course

should be the value we had before.

I don't wanna reset this to be empty

because the input could blur

after the user entered something.

I don't wanna lose that.

So therefore I'll use my last state snapshot,

which I get here.

And that this is guaranteed

to be the absolute last state snapshot.

React gives us this state snapshot

and it makes sure that it's the latest one.

So here we can safely access state.value, for example,

to access the last value that was entered for the email.

And for the validity, we can there for check

if the state value is valid,

by again, repeating our validity check here.

And of course you could always refactor this check

into a function,

but I don't want to make this overly complicated.

So with this, we now have this extra action.

And as a result, if I log out here,

you see initially it's blurred, which makes sense actually,

because my initial value for isValid is false.

If I set this to undefined or to null instead,

you'll see it's not treated as invalid.

It's not treated as if it was blurred from the beginning on.

But if I click in there it is.

And if I then start typing, I'm getting an error.

Cannot read property 'includes' of undefined.

And what could be causing that?

Well, it looks like we're having problems

running this code here,

because that clearly has to be the action that triggered.

And that's simply because here I'm checking action.valid.

Of course it should be action.val.

So the value I'm retrieving here.

So a simple typo here, my mistake.

Let's reload.

Now I can type here.

And then that all seems to work.

And overall, this works as before,

without the debouncing, because I commented out that code,

but the general form validation works,

now with the help of useReducer.

And this allows us to group this emailState together

and manage it in one place.

It's a little bit more set up up here,

but on the other hand, the code in the component

then is simpler because there, we only need to dispatch

and not do any validation or anything like that.

So here's a task for you now.

Take this.

How do you find the finish code snapshot,

and do the same for the password.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.