Get undefined error while trying to follow tutorial

Github : https://github.com/nileshstailor/react-contact-manager

I followed this tutorial/book : https://www.sitepoint.com/premium/books/build-a-node-js-crud-app-using-react-and-feathers/read/1 and I am in the section that deals with “Handle Create Requests Using React Hook Forms” and the code is verbatim to the one in the tutorial - so not sure what I am doing wrong.

Following is the error I see. Seems like “error” is coming up as null so error.name is giving the undefined warning.

TypeError: Cannot read property ‘name’ of undefined

ContactForm

c:/react/react-contact-manager/src/components/contact-form.js:16

13 | <h1 style={{ marginTop: '1em' }}>Add New Contact</h1>  
14 | <Form onSubmit={handleSubmit(onSubmit)} loading={state.loading}>  
15 |   <Form.Group widths="equal">> 
16 |     <Form.Field className={classnames({ error: errors.name })}>     
| ^  17 |       <label htmlFor="name.first">  
18 |         First Name  
19 |         <input

Apparently the version that the tutorial was developed in and the latest code cause a discrepancy.
FYI for anyone in the future just change package.json to used the sameones from the github repo of the tutorial and then use yarn -force to compile using the old package files and not the latest.

3 Likes

Hey there,

Welcome to JavaScript. Have a nice stay :slight_smile:

Thanks for taking the time to follow up. I’ve just had a look and it seems the problem you are experiencing is being caused by the React Hook Form library. The tutorial was written using version 6, whereas if you run yarn add react-hook-form you will pull in version 7.

Version 7 introduced a couple of breaking changes. You can read about them here:

https://react-hook-form.com/migrate-v6-to-v7/

In the component you are having trouble with, the two problematic things are the errors object and the register method. These have to be imported / used slightly differently.

Here is the complete code for the component which will work with v7 of React Hook Form:

import React, { useContext } from 'react';
import { Form, Grid, Button } from 'semantic-ui-react';
import { useForm } from 'react-hook-form';
import classnames from 'classnames';
import { ContactContext } from '../context/contact-context';
const ContactForm = () => {
  const [state] = useContext(ContactContext);
  const {
    register,
    handleSubmit,

    formState: {
      errors,
    },
  } = useForm();
  const onSubmit = data => console.log(data);
  return (
    <Grid centered columns={2}>
      <Grid.Column>
        <h1 style={{ marginTop: '1em' }}>Add New Contact</h1>
        <Form onSubmit={handleSubmit(onSubmit)} loading={state.loading}>
          <Form.Group widths="equal">
            <Form.Field className={classnames({ error: errors.name })}>
              <label htmlFor="name.first">
                First Name
                <input
                  id="name.first"
                  {...register('name.first', { required: true, minLength: 2 })}
                  type="text"
                  placeholder="First Name" />
              </label>
              <span className="error">
                {errors.name &&
                  errors.name.first.type === 'required' &&
                  'You need to provide First Name'}
              </span>
              <span className="error">
                {errors.name &&
                  errors.name.first.type === 'minLength' &&
                  'Must be 2 or more characters'}
              </span>
            </Form.Field>
            <Form.Field>
              <label htmlFor="name.last">
                Last Name
                <input
                  id="name.last"
                  {...register('name.last')}
                  type="text"
                  placeholder="Last Name" />
              </label>
            </Form.Field>
          </Form.Group>
          <Form.Field className={classnames({ error: errors.phone })}>
            <label htmlFor="phone">
              Phone
              <input
                id="phone"
                {...register('phone', {
                  required: true,
                  pattern: /^\+(?:[0-9] ?){6,14}[0-9]$/,
                })}
                type="text"
                placeholder="Phone" />
            </label>
            <span className="error">
              {errors.phone &&
                errors.phone.type === 'required' &&
                'You need to provide a Phone number'}
            </span>
            <span className="error">
              {errors.phone &&
                errors.phone.type === 'pattern' &&
                'Phone number must be in International format'}
            </span>
          </Form.Field>
          <Form.Field className={classnames({ error: errors.email })}>
            <label htmlFor="email">
              Email
              <input
                id="email"
                {...register('email', {
                  required: true,
                  pattern: /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/,
                })}
                type="text"
                placeholder="Email" />
            </label>
            <span className="error">
              {errors.email &&
                errors.email.type === 'required' &&
                'You need to provide an Email address'}
            </span>
            <span className="error">
              {errors.email &&
                errors.email.type === 'pattern' &&
                'Invalid email address'}
            </span>
          </Form.Field>
          <Button primary type="submit">
            Save
          </Button>
        </Form>
      </Grid.Column>
    </Grid>
  );
}
export default ContactForm;

Here are the diffs of what changed:

- const { register, errors, handleSubmit } = useForm();

+ const {
+   register,
+   handleSubmit,
+   formState: {
+     errors,
+   },
+ } = useForm();

...

<input
  id="name.first"
- name="name.first"
  type="text"
  placeholder="First Name"
- ref={register({ required: true, minLength: 2 })}
/>

<input
  id="name.first"
+  {...register('name.first', { required: true, minLength: 2 })}
  type="text"
  placeholder="First Name" />

<!-- And so on for the other fields -->

HTH

2 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.