1

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>
}
jamesmungai
  • 119
  • 2
  • 8

3 Answers3

1

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;
    }
visizky
  • 701
  • 1
  • 8
  • 27
  • the switch statement is after i have logged the event and discovered that e.target is null. Do you know why the e.target is null but it is not when i switch to class component? – jamesmungai Mar 05 '20 at 12:58
  • e.target is not null, open the link and proceed to type on any input tag and open the console to verify. – visizky Mar 05 '20 at 13:25
1

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

Ed Lucas
  • 5,955
  • 4
  • 30
  • 42
0

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>
Brian Thompson
  • 13,263
  • 4
  • 23
  • 43