jamesmungai
jamesmungai

Reputation: 159

event.Target value is null for react form using hooks to handle change

I'm trying to study react hooks. this is a sign-up form that works well when using the classical class component with internal state and controlled forms. but when I try to use react hooks like this and type on the input it just will not display what I'm typing.

I have logged the event and have realized that the problem could be that the target value is null. Can somebody explain to me why this could be the case?

const SignUp = props => {
  const [displayName, setDisplayName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");

  const handleChange = e => {
    console.log(e);
    const { name, value } = e.target;
    switch (name) {
      case name === "displayName":
        setDisplayName(value);
      case name === "email":
        setEmail(value);
      case name === "password":
        setPassword(value);
      case name === "confirmPassword":
        setConfirmPassword(value);
    }
  };
  const handleSubmit = async e => {
    console.log(e);
    e.preventDefault();
    if (password !== confirmPassword) {
      alert("passwords do not match");
      return;
    }
    const { signUpStart } = props;
    signUpStart({ email, password, displayName });
  };

  return (
    <div className="sign-up-section">
      <form onSubmit={handleSubmit}>
        <FormInput
          type="text"
          name="displayName"
          handleChange={handleChange}
          value={displayName}
          label="display name"
        />
        <FormInput
          type="email"
          required
          name="email"
          value={email}
          handleChange={handleChange}
          label="email"
        />
        <FormInput
          type="password"
          name="password"
          handleChange={handleChange}
          value={password}
          label="password"
        />
        <FormInput
          type="psssword"
          name="confirmPassword"
          handleChange={handleChange}
          value={confirmPassword}
          label="comfirmPassword"
        />
        <Button type="submit" name="password" label="SIGN" />
      </form>
    </div>
  );
};


const FormInput =({label,handleChange, ...otherProps})=>{
    return <div className='group'>
        <input {...otherProps} onChange={handleChange} className='form-input'/>
        {
            label?(<label className={`${otherProps.value.length? 'shrink':''} form-input-label` }>{label}</label>):null
        }
    </div>
}

Upvotes: 1

Views: 8622

Answers (3)

Brian Thompson
Brian Thompson

Reputation: 14355

As you can see below, the problem isn't that e.target is null or undefined. The problem is actually in your switch statement.

You're blending syntax of switch and if else here case name === "displayName":. The switch automatically does the name == part. In your case, all you need to do is put what name should be equal to - not the whole expression.

Change as shown below, with correct case's and with break's after the state update.

const {useState, useEffect} = React;

const SignUp = props => {
  const [displayName, setDisplayName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");

  const handleChange = e => {
    console.log(e.target.name); // Logs correctly
    console.log(e.target.value); // Logs correctly
    const { name, value } = e.target;
    switch (name) {
      case "displayName":
        setDisplayName(value);
        break;
      case "email":
        setEmail(value);
        break;
      case "password":
        setPassword(value);
        break;
      case "confirmPassword":
        setConfirmPassword(value);
        break;
    }
  };
  
  const handleSubmit = e => {
    console.log(e);
    e.preventDefault();
    if (password !== confirmPassword) {
      alert("passwords do not match");
      return;
    }
    const { signUpStart } = props;
    //signUpStart({ email, password, displayName });
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <FormInput
          type="text"
          name="displayName"
          handleChange={handleChange}
          value={displayName}
          label="display name"
        />
        <FormInput
          type="email"
          required
          name="email"
          value={email}
          handleChange={handleChange}
          label="email"
        />
        <FormInput
          type="password"
          name="password"
          handleChange={handleChange}
          value={password}
          label="password"
        />
        <FormInput
          type="psssword"
          name="confirmPassword"
          handleChange={handleChange}
          value={confirmPassword}
          label="comfirmPassword"
        />
        <button type="submit" name="password">Sign</button>
      </form>
    </div>
  );
};


const FormInput = ({label,handleChange, ...otherProps}) => {
  return (
    <div>
      <input 
        {...otherProps} 
        onChange={handleChange} 
        className='form-input'
      />
      {label ?
        <label>{label}</label>
      : null}
    </div>
  );
}

ReactDOM.render(<SignUp />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Upvotes: 0

Ed Lucas
Ed Lucas

Reputation: 7305

Have you tried using e.currentTarget instead?

const { name, value } = e.currentTarget;

That will ensure that you will get the element to which the event listener is attached.

See: What is the exact difference between currentTarget property and target property in javascript

Upvotes: 1

visizky
visizky

Reputation: 761

https://stackblitz.com/edit/react-form-hooks you want to setState for each change on the input field, so the onChange callback function will be called whenever there is a change to the input field.

coming to your callback function, the switch case should be like this:

    switch(cond){
    case 'cond1':
                 execute;
                 break;
    }

Upvotes: 1

Related Questions