Who This Is For
- You want dynamic (that is, validate dates before submission) and simple date validation for a non-complex form.
- You are using React Hooks and functional components. You can reverse engineer the code if you are using classes.
- You want a codesand box with clear explanations of how & why.
- You want to know why they are called Hooks.
Note 1 - I assume you understand the useState()
hook.
Note 2 - I’m using moment.js. If you are using a modern/supported date/time package, your implementation might vary.
Note 3 - This is Typescript/React. If you are new to Typescript, know that this bit of code: : boolean
or : string
after a variable declaration indicates the data type to check for. Otherwise, the implementation is the same.
Sandbox
Step 1 - The Date Input Setup
The calendar is built with the MaterialUI KeyboardDatePicker; see the sandbox for the full code. The code snippet below shows the key parts for date validation in the onChange callback:
<KeyboardDatePicker
label="Start Date"
// name="date” note: intentionally commented out
value={dates.startDate}
onChange={(value) => handleDateChange("startDate", value)} // ←-important part
/>
For most form inputs, we set state using the event.target.name
and event.target.value
in the handleChange
callback.
However, the event
in this case is different. The event is a moment.js
object{}. Use console.log
or debugger
to see the event
looks like this:
// from the console
> event
Moment {_isAMomentObject: true, _i: Tue Dec 15 2020 09:56:21 GMT-0800 (Pacific Standard Time), _isUTC: false, _pf: {…}, _locale: Locale, …}
Because event
is a moment.js
object{}, we do not have a name={something}
property via event.target.name.
So how do we set the value to the correct state variable?
Create a generic event handler to set startDate
and endDate
by passing the handleDateChange
two arguments: a string and a value. The string is a name to use as a reference (startDate
in this case) and the event (called value
in this case, which is moment.js object and NOT value={dates.startDate}
)
Note: you could also create a setStartDate()
and setEndDate()
via useState()
instead of a generic handleEvent
.
Step 2 - Validation Setup
Determine if your dates can be the same or different. This feature allows the same start and end date, requiring comparison with <=
.
The ternary operators change two boolean values (dateValidity
and formValidity
) and ternary controls the display of any error message.
The dateValidity
connects to the KeyboardDatePicker
error property (error={errors.dateValidity}
); the input changes color depending on this error state.
Form submission is controlled via formValidity
state. If there is an error, the form displays the error and prevents submission until the error is fixed.
Step 3 - useEffect() Hook To Control Timing
For a user to see the error messages and error styling, first set the dates
state variables in handleDateChange().
After handleDateChange()
runs, where and how to do the validation? The short answer? useEffect() hook.
useEffect(() => {
validateDates();
}, [dates]); // ←-this is the array argument.
This useEffect hook executes the callback function (validationDates()
in this case) only if the state in the array argument ([dates]
) changes.
If you attempt to call validationDates()
inside handleDateChange()
or as a second callback to onChange
, you experience asynchronous update and UX issues.
Note: the array argument in useEffects
can take multiple state items (or none). If any one of the state items changes, the callback function runs. useEffects
is worth understanding. Check the references below for suggested readings and videos.
Why Are They Called Hooks?
When I first heard Hooks, I visualized setting something like fishing hooks into my code. The hook name, because of my mental picture, didn’t provide a clue for use.
The React.js explanations also didn’t help:
“Hooks allow you to reuse stateful logic without changing your component hierarchy.”
Ok. Fine.
But why the name Hook?
In science class, we learn about classes of animals (among other categories of classes). So classes, as a term of code abstraction, makes sense, but hooks as a term? Hmm...
“Hooks are functions that let you “hook into” React state and lifecycle features from function components”
Ok, a better attempt to explain the name. But this definition is a tautology (fancy word meaning to define X with different but similar words).
TL:DR - A Better Hook Definition - hooks let you connect to or or join your functional component to a state object; previously you could not hook your functional component to state.
This Intro to Hooks - Official High Level Overview of Hooks
is helpful in understanding the problem hooks seek to solve.
Feedback?
Have thoughts on date validations or the above implementation?
If so, drop a note. I'd love to hear and see your examples, explanations, and other details to clarify how/why/when.
Resources
*Intro to Hooks - Official High Level View of Hooks
*Hooks Overview - Official
*Using React Hooks - LinkedIn Learning - The clearest explanations I’ve found for why and how to use hooks. Worth the cost of a membership.
*3 Rules of React State Management
*React Form Validation Using React Hooks - A different implementation of validating forms with useCallBack()
hooks and form abstraction.
*How to Build Custom Forms with React Hooks - Building a whole form with hooks and abstraction.
Top comments (0)