DEV Community

loading...
Cover image for Date Validation in Forms for Beyond Beginners - React - MaterialUI - Hooks -

Date Validation in Forms for Beyond Beginners - React - MaterialUI - Hooks -

brad_beggs profile image Brad Beggs ・4 min read

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
 />
Enter fullscreen mode Exit fullscreen mode

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, }
Enter fullscreen mode Exit fullscreen mode

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. 
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)

pic
Editor guide