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
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
Now, it's of course, up to you
which validation logic you wanna apply.
I wanna keep it fairly simple.
I wanna check that all my values are not empty
and that the postal cost, let's say,
is exactly five digits long.
For this, I'll add a couple of helper functions here outside
of the component function
and the first one is the isEmpty helper function
where I get a value and return true
if value is empty.
For that I call trim on value
and then check if the length
is equal to zero or simply if the trimmed string
is equal to an empty string.
And the second helper function, which I'll add here
is the isNotFiveChars,
whatever you wanna name it,
where I get a value
and I also trim this
and I then check if the length is not equal to five.
So if it's not five characters long.
Now, these two helper functions can be used
to now validate those entered values.
So we can add a new constant, enteredNameIsValid,
and that should be true
if we can call isEmpty
and pass in the enteredName
and that then returns false.
So if it it's not empty.
So enteredNameIsValid is not isEmpty enteredName.
If the enteredName is not empty, this is valid.
And I'll repeat this for the street.
So the enteredStreetIsValid
if not isEmpty enteredStreet.
And I'll repeat that for the city.
So the enteredCityIsValid
if not isEmpty enteredCity.
And now for the enteredPostalCode to be valid,
I will check if not isNotFiveChars
for the enteredPostalCode.
And that can be a bit confusing to read.
Not isNot.
We could also simply name this isFiveChars up there
and check for equality like this.
And then say it's valid if isFiveChars.
That's the simpler form of writing this.
We could do something similar for isEmpty
and check for the opposite
but I think that's not too tricky to understand.
Now we've got these four helper variables here,
which hold true or false.
And now we can check if the overall form is valid
by combining all these values.
Only if all four constants here have a value of true,
the overall form is valid.
And I'm doing this very explicitly step by step here
to make it as easy to follow along as possible.
So now we can check if enteredNameIsValid.
And enteredStreetIsValid.
Combine that with enteredCityIsValid
and last but not least with enteredPostalCodeIsValid.
And only if all four together are true,
formIsValid will be true.
So if formIsValid, we can now submit the cart data
because here we know that we gathered valid data
and we can now proceed with that.
But if the form is not valid, we wanna show an error.
And therefore, that's what I'll actually check for here.
I'll check if not formIsValid
and then I wanna set an error
and give some feedback to the user regarding
what went wrong.
For that, I will, first of all,
return here to not continue with code execution
because later I will submit the cart data here
and I don't wanna reach that code
if the form is invalid.
But before we make it to this if check,
I wanna update some state to give the user some feedback.
And here I wanna manage four pieces of state
since I have four inputs.
And therefore, again we could use useReducer
to kind of combine that all
or to manage that with a reducer function in general
but I will stick to useState here.
You'll learn about useReducer and all of that
in the forms module though.
Now, we'll use useState
and I will register a new state here with useState.
And here, oops, not like this,
instead some useState with useState.
And here we could use four individual state slices
or one combined state slice.
And I'll go for the one combined state slice
to mix things up.
So here I have my formInputsValidity
and a function to set the formInputsValidity.
And now that will be an object
where I have a name field, a street field,
a city field and a postalCode field
and now we need to give those fields some values.
And I simply wanna have true or false as values here,
determining whether the field is valid or not.
And initially, I'll treat them as valid
even though they technically aren't
but I don't wanna show error messages at the beginning.
Now, we could work with the touched state
in addition to the validity state
as we did it in the forms module
but to keep things a bit shorter here
and since we don't have an as elaborate validation approach
as we did in the forms module,
I will stick to a starting value of true here.
Now the goal is to update the correct field
for the different inputs here
when we submitted the form
to update those true values
with the actual validity after we tried
to submit the form.
So for this, maybe before we even derive formIsValid,
I will set the FormInputsValidity state to new object.
And here I wanna set the name field
to enteredNameIsValid,
the street field to enteredStreetIsValid and so on.
So I'll use those inferred validities,
which we infer here
as new values for the different keys in this state object.
So here we have the enteredPostalCodeIsValid value.
Now, we don't need the function form
of this state updating function for updating here
because I am overriding the entire state
with a brand new object
where I do assign new values to all my keys.
And with that, we have information
about the validity of the different fields.
We can now utilize that in the JSX code down there,
for example, to show an error message.
Here for the name,
we could check if formInputsValidity.name,
so if we dive into the name field,
if that is not true,
hence the exclamation mark,
then we wanna show a paragraph
where we say please enter a valid name.
Now, if we do that and save this,
you'll see initially that's empty
but if I try to confirm this,
I now get this error
and there, of course, we can now repeat that
for all the inputs.
So here we check .street
and say please enter a valid street.
And here we do it for the postal code.
So .postalCode and then we say
please enter a valid postal code,
five characters long.
And last but not least,
here we check for .city
and say please enter a valid city.
I also prepared some extra styles
in the Checkout.module.css file
where I have an invalid class,
which we can add to these divs here
if an input is invalid to show extra error styles.
So here on the name input, for example,
instead of just adding the control class,
I'll set up a template literal here
to always inject the control class into the string
but to also inject another class
if that input should be invalid.
So here we can check if formInputsValidity.name,
if that is true, I don't wanna add any extra string
to that class's string
but if it's false, I wanna add classes.invalid here.
With that, we add the extra invalid class
to that list of classes if that input is not valid.
And of course, instead of doing that in line here,
we could also grab that code
and add a new constant.
nameControlClasses and store that value
in that constant so that down there,
we just point at nameControlClasses like this.
That's an alternative way of doing that.
And then now we can also repeat that
for the street
by checking for formInputsValidity.street
and we do that for the other inputs for that as well.
And we have some code duplication here
but again, that's also something we talked about
in the forms module
and we could, for example, reduce that
by creating a separate input component
or reduce some other duplication
by adding a custom forms hook, for example.
For the moment here, I'll stick to this approach
and hence, I'll add a postalCodeControlClasses constant
where I check formInputsValidity.postalCode
and then add another constant,
the cityControlClasses
where we check formInputsValidity.city.
And now we just need to assign these constants
to the different divs.
So here for the street div,
it's the streetControlClasses constant,
which we assign as a value for className.
Here for the postal code, it's the postalCodeControlClasses,
which we assign as a value to className
and for the city, it's the cityControlClasses.
And with those changes made,
if we save this, if I confirm this,
we get a bunch of error styles
and of course, if I enter something valid
and I confirm this,
it's not showing up for that input again.
So you see that this now works.
Now, feel free to definitely turn this
into a more elaborate form validation here,
for example, by adding a custom form hook
or by also listening to the touch state
and clearing errors as you start typing.
We did dive into all of that in the form section.
I just didn't want to bloat this module again
with all the topics covered there.
Instead, the goal was to pull out the essence
of that module and just add some basic form validation here.
And therefore, with all of that,
we can now also confirm this without errors
if we enter valid values.
And hence now as a last step,
let's make sure that those values
are fetched and are sent to the backend.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.