Home > Software engineering >  form.js:24 Uncaught TypeError: Cannot destructure property 'name' of 'e.target'
form.js:24 Uncaught TypeError: Cannot destructure property 'name' of 'e.target'

Time:08-17

im getting some error saying cant destructure the property 'name' of e.target undefined I will be grateful for any help. unable to assign any value in the input field. I need to sign up as a client, but when I enter the value they can't assign, what can i do ?

export const Form = ({ sx, onSubmit }) => {
      const [form, setForm] = useState({
        email: {value: "", error: null},
        password: {value: "", error: null},
        role: roles.client,
      });

      const [errors, setErrors] = useState({
        email: null,
        password: null,
        role: null,
      });

      const handleChange = (e) => {
        const { name, value } = e.target;

        setForm({ ...form, [name]: value });

        // authValidators[name]({
        //   value,
        //   cb: (error) => setErrors((prev) => ({ ...prev, ...error })),
        // });
      };

      const handleSubmit = () => {
        // for (let key in form) {
        //   if (key === "role") continue;
        //   // authValidators[key]({
        //   //   value: form[key],
        //   //   cb: (error) => setErrors((prev) => ({ ...prev, ...error })),
        //   // });
        // }

        for (let key in form) {
          if (form[key].length === 0 || errors[key]) {
            return;
          }
        }

        onSubmit(form);
      };

      return (
        <Box sx={sx.root}>
          <EmailInput
            sx={sx.input}
            valueObj={form.email}
            error={errors.email !== null}
            errorMessage={errors.email}
            onChange={handleChange}
          />
          <PasswordInput
            sx={sx.input}
            valueObj={form.password}
            error={errors.password !== null}
            errorMessage={errors.password}
            onChange={handleChange}
          />
          <GroupToggleField
            sx={sx.toggleButton}
            value={form.role}
            onChange={(value) => setForm({ ...form, role: value })}
            options={options}
          />
          <Button sx={sx.button} onClick={handleSubmit}>
            Sign In
          </Button>
        </Box>
      );
    };

    const options = [
      { value: roles.client, title: "Client" },
      { value: roles.member, title: "Crew Member" },
    ];

i also writen a code for email and password separatly this is my email code:

export const EmailInput = ({
      fieldname,
      label,
      placeHolder,
      valueObj,
      onChange,
    }) => {
      const handleChange = ({ target: { value } }) => {
        let error = null;

        const re = /\S @\S \.\S /;
        if (!re.test(value)) {
          error = `${label} proper email address`;
        }

        if (value.length === 0) {
          error = `${label} field cannot be empty`;
        }

        onChange(fieldname, { value, error });
      };

      return (
        <TextField
          onFocus={handleChange}
          onChange={handleChange}
          value={valueObj.value}
          error={valueObj.error !== null}
          helperText={valueObj.error}
          label={label}
          placeholder={placeHolder}
          margin="normal"
          size="small"
          fullWidth
        />
      );
    };

this is my password code:

export const PasswordInput = ({ valueObj, onChange }) => {
      const [showPassword, setShowPassword] = useState(false);

      const handleShowPassword = () => setShowPassword((prev) => !prev);

      const handleChange = ({ target: { name, value } }) => {
        let error = null;

        if (value.length <= 5) {
          error = "Password must be minimum 6 characters";
        }

        if (value.length === 0) {
          error = "Password field cannot be empty";
        }

        onChange(name, { value, error });
      };

      const toggle = (
        <InputAdornment position="end">
          <IconButton onClick={handleShowPassword} edge="end">
            {showPassword ? (
              <VisibilityOff fontSize="small" />
            ) : (
              <Visibility fontSize="small" />
            )}
          </IconButton>
        </InputAdornment>
      );

      return (
        <TextField
          onFocus={handleChange}
          onChange={handleChange}
          value={valueObj.value}
          error={valueObj.error !== null}
          helperText={valueObj.error}
          InputProps={{ endAdornment: toggle }}
          type={showPassword ? "text" : "password"}
          label="Password"
          name="password"
          margin="normal"
          size="small"
          fullWidth
        />
      );
    };

CodePudding user response:

There's a lot here, so I'm taking a quick first pass.

Let's look at your EmailInput component. It takes onChange as a prop. When the internal TextField component experiences a "change" event, it calls the internal function EmailInput > handleChange; that in turn calls whatever function was passed in the onChange prop to the EmailInput component.

So in EmailInput, this line is calling whatever function was passed to onChange as a prop:

onChange(fieldname, { value, error });

So the first argument is fieldname, which is probably a String. The second argument is an Object with properties value and error. What function is being called? Let's look at your Form component:

const handleChange = (e) => {
  const { name, value } = e.target;

  setForm({ ...form, [name]: value });

  // authValidators[name]({
  //   value,
  //   cb: (error) => setErrors((prev) => ({ ...prev, ...error })),
  // });
};

// ... Skip a few lines...

  <EmailInput
    sx={sx.input}
    valueObj={form.email}
    error={errors.email !== null}
    errorMessage={errors.email}
    onChange={handleChange}
  />

So you see, handleChange is the actual function that we call inside EmailComponent when we call onChange. Right now, handleChange only takes one argument, "e", though as you can see above we are passing it two. Furthermore, it seems to expect e to be an Object with a target property, but it is actually a String, fieldname.

Therefore, the handleChange function inside the Form component should look something like this:

const handleChange = (fieldName, { value }) => {
  setForm({ ...form, [fieldName]: value });
};

You might run into a problem because I don't see you providing the fieldname prop to EmailInput; maybe add something like this here:

  <EmailInput
    fieldname="email" // Add this line
    sx={sx.input}
    valueObj={form.email}
    error={errors.email !== null}
    errorMessage={errors.email}
    onChange={handleChange}
  />
  • Related