重用 AuthForm 组件而不在状态中发送不必要的信息

Reusing an AuthForm component without sending unnecessary info in state

我在 /signup 和 /login 页面上都使用了一个 AuthForm 组件,我使用 formType 属性来区分这两者。注册页面需要一些额外的字段,包括性别和出生日期(可能是将来的地址),而登录表单可以相当简单。

从显示的角度来看,这很简单,因为我可以根据 formType 属性的值显示或隐藏那些额外的字段。它变得复杂的地方是状态。

我考虑过两种不同的状态管理方法:1) 使用 useFormInput() 挂钩,以及 2) 使用 useState 挂钩结合状态对象(模仿有状态组件方法)。

选项 1:

const useFormInput = (initialValue) => {
  const [value, setValue] = useState(initialValue);

  function handleChange(e) {
    setValue(e.target.value);
  }

  return {
    value,
    onChange: handleChange
  };
}

const AuthForm = ({ buttonText, formType, onAuth }) => {

  const email = useFormInput(''); 
  const password = useFormInput(''); 
  ...

  const handleSubmit = (e) => {
    e.preventDefault();
    onAuth(formType, {email, password, etc); 

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">E-mail</label>
      <input
        id="email"
        name="email"
        type="text"
        {...email}
      />
   ...
  )
};
  }

选项 2

const AuthForm = ({ buttonText, formType, onAuth }) => {

  const [state , setState] = useState({
      email : "",
      password : "",
      firstName: "",
      lastName: "",
      gender: "",
      dob: ""
  })

  const handleChange = e => {
      const {name , value} = e.target;
      setState( prevState => ({
          ...prevState,
          [name] : value
      }))
  }

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(state);
    onAuth(formType, state);

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">E-mail</label>
      <input
        id="email"
        name="email"
        onChange={handleChange}
        type="text"
        value={state.email}
      />
   ...
  )
};
  }

无论采用哪种方法,我似乎都无法避免必须声明每个状态变量。当我在选项 2 中设置 state = {} 时,我收到有关将不受控组件更改为受控组件的错误。当我声明我所有的状态变量时,这意味着我的登录表单将在状态中包含 gender="",这将覆盖我数据库中的值。

我怎样才能 A) 避免完全声明状态变量,或者 B) 使我的最终状态只包含适合 AuthForm 使用上下文的字段?

您可以尝试根据 formType 创建初始状态(选项 2)。

const AuthForm = ({ buttonText, formType, onAuth }) => {

  initialStateLogin = {
      email : "",
      password : "",
  };

  initialStateSignup = {
      email : "",
      password : "",
      firstName: "",
      lastName: "",
      gender: "",
      dob: ""
  };

  const [state , setState] = useState(formType === 'login' ? initialStateLogin : initialStateSignup);

  //rest of the code..

}