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
So as mentioned at the end of last lecture,
we have a working code here
but we have a lot of duplication.
We're not duplicating the exact same words.
These constants are named differently.
This logic here is different,
but the overall logic, the overall structure
is of course exactly the same.
And if we think about a more complex form like this one
which actually isn't too complex
but which has at least three inputs
then we would be repeating that same structure,
that same code in the end three times.
And that's not what we wanna do.
So instead we typically want to outsource
some logic somewhere.
We don't want to retype and repeat it all the time.
And how can we best do that?
You could consider creating a separate input Component
so that you will replace this code down there
with the input Component.
And inside of that input Component you then have
that logic for validating it,
for checking its touch status and so on.
And that would probably work.
That is something you could do.
The only thing that could become a bit more tricky then
or where you would need to find a solution
would be for managing the overall form validity.
Because if you manage every input
as an individual closed thing,
and you know if the input is valid or not,
you then also need a way of letting the overall form
know if it's valid or not.
And that could certainly be done
with props and passing functions to props
and calling them from inside the input Component and so on.
But there always is another approach
which I tend to prefer here.
And that would be a custom hook.
We can use a custom hook to manage all
that state logic in there.
And let me show you how we could do that.
For this I'll add a new folder in this project here.
I'll name it hooks next to Components
and I'll then add a use input JS file
because it will be a hook for managing the state
and the logic for an input.
So in here, I'll add my use input hook function
and I will export it as a default here
and now in this hook function, I want to manage the value
of a given input, the touch state.
I want to infer its validity.
Also combined of course with the touch state.
Now, of course this hook should then
also be flexible though.
The concrete validation logic should be passed into the hook
from outside, but that is something we can build.
And I'll start by copying the entered name
and entered name touched states here
and add them into use input function.
For this of course here in this use input JS file
we need to import useState from React.
Then I'll rename this here to entered value
and set entered value to make it more generic.
And that here is touched and set is touched.
Now as a next step, we can copy our inferred state here
so to say.
So these two constants entered name as valid
and name input as invalid.
I'll copy those and also give those better names.
I'll name the first one value is valid
and the second one could get a name
of has error because in the end here we control
whether an error should be shown or not.
Now for value is valid.
I check the entered value here and for has error
I then use value is valid.
And if it's not valid, combined with is touched.
I find out whether we wanna show an error or not.
Now this validation logic however,
shouldn't be hard-coded here.
Instead I want to get the logic for that from outside
where this hook gets used.
But that's no problem.
We can expect a function
as an argument to this custom hook function.
Let's say the validate value function.
So I expect that this parameter receives a function
as a value.
So that here for a value is valid.
I can execute validate value
and just pass in the entered value we currently have.
And then this hook could return something.
It could return an object, could also be an array,
but one of the two, because I wanna return more
than one thing.
And then this object I'll return the value
which is the entered value.
I'll return has error
which holds the results stored in has error.
And since we got the same names here
we can use the modern JavaScript syntax
of just listing this once.
And it'll automatically be expanded
to this here behind the scenes.
And we will also need a way
of letting the Components that uses this hook
set the entered value
and set detached state thereafter.
Now for that we could go back to simple input
and copy the name input change handler
into use input as a function
and copy the name input blur handler into our hook function.
And rename the functions to value change handler
and call set entered value here.
And then all the input blur handler
and call set is touched here.
And when we return, I wanna expose those functions.
So I'll expose to value change handler
and the input blur handler.
So that these functions which are defined in the hook
can be called from the place where to hook is being used.
So can be called from the Components that uses that hook.
Now with that can use this custom hook
in the simple input Component.
There we can now import use input
from going up one level hooks use input
and then call use input here and then extract values
from the result returned by use input.
Use input returns such an object
hence we can use object de-structuring to pull
out those keys from that returned object
and store the values and brand new constants.
So we can for example, extract the value
and then also assign an alias
with the colon here and name this entered name
and also pull out the has error state
and maybe named as name input has error.
Those aliases of course are up to you
and also extract the value change handler
and give this an alias of name changed handler
and get access to the input blur handler
and give it an alias of name blur handler
or something like this.
So that this is how we use the hook,
but we also need to pass a value into the hook.
And that's this validate value function, which we call here.
So for this we could define an inline function here
where we get some value and then return the result
of calling trim on that value and comparing it
with an empty string.
So the logic we have down there just
with value instead of entered name.
Now this is an anonymous error function
which is not executed here but defined here in line
which is then passed to use input.
So it's received on this validate value parameter.
And then this function, this function here
which be defined here is actually executed
in this line here.
That's where it's being called.
And the entered value
which is this state we're managing here is the value passed
into this function.
Can be a bit tricky to wrap your head around,
but in the end it's just regular JavaScript
where we are passing a function
as a value to another function.
And with that, we can customize the validation logic
in the Component where we need this hook
and still execute it inside of the hook.
And that now allows us to get rid
of these two state slices here for the entered name.
It allows us to get rid of these two constants here.
Entered name is valid and name input is invalid.
And instead use these pulled out Constants here.
And for example here we are then actually
missing information about the validity.
We know if there is an error or not
but that's not just the validity
but the validity combined with the touch state.
And therefore to expose just the validity
of an input to the Component.
I will actually also return value is valid here
maybe on it is valid key.
So that we also expose that information
from the hook to the Component where we use it.
And then in the Component we can also extract is valid
and store this in a entered name is valid
constant by assigning this alias
and then entered name is valid can be used here again.
Now we can get rid of the name inputs change handler
function here and of the name input blur handler.
And instead we'll use the name changed handler
and the name blur handler
which we're getting out of the hook.
So down there in JSX.
I connect the name change handler
and the name blur handler.
Here instead of using name input is invalid.
I will use name has error, name input has error
which we're also getting from the custom hook.
And then here for the form submission handler
where I want to change the touch status
and where I want to reset the form.
We can get rid of this line of code
because the form can't be submitted
if the inputs are invalid anyways.
So we don't need to Mark the inputs as touched here
but of course you want to be able to reset the form.
And therefore we can go back to the custom hook
and add a third function here.
Reset function where we simply call set entered value
and set this to an empty string.
And set is touched and set this to false.
And then we just need to expose that.
So that we also return the reset function
as a value in a reset key in that overall returned object.
And in simple input JS
we can then get access to this reset function
and maybe name it reset name input, give it this alias.
And then the form submission handlers.
We can then just call reset name input here.
Now down there where we inferred a CSS classes.
I now wanna use the name input has error data piece
which we get from the hook.
And with that, if we reload this name behaves just like
before and the overall form also behaves just like before.
If I enter something valid here, we can submit it.
If this is invalid, we can't.
If I reload, if I click in there
and out of there, it's invalid.
This all works like before but now with a custom hook
and now we can therefore also replace the email state
the entered email state with our custom hook.
Feel free to try this on your own.
We're going to do it together in the next lecture.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.