如何使用钩子将该类组件实现为功能组件?

时间:2020-06-27 15:46:11

标签: javascript reactjs react-hooks

我正在创建一个包含多个字段的注册表单,名字,姓氏,电子邮件和密码:

代码:

class Sign Up extends Component {
  state={
      firstName: '',
      lastName: '',
      email: '',
      password: '',
   }

   handleChange(e){
     this.setState({
       [e.target.id]: e.target.value
    })
   }
   return (
     <form onSubmit={handleSubmit}>
         <h5>Sign Up</h5>

          <div className="input-field">
              <label htmlFor="firstName">First Name</label>
              <input type="text" id="firstName" onChange={handleChange}/>
         </div>

         <div className="input-field">
             <label htmlFor="lastName"></label>
             <input type="text" id="lastName" onChange={handleChange}/ >
         </div>

         <div className="input-field">
            <label htmlFor="email"></label>
            <input type="email" onChange={handleChange} />
         </div>

         <div className="input-field">
             <label htmlFor="password"></label>
             <input type="password" onChange={handleChange} />
         </div>

         <button className="btn pink z-depth-0 lighten-1 text-grey">Sign up</button>
     </form>
  )

}

我试图将其转换为功能组件,而在状态部分我所能做的就是:

const [firstName, setFirstName] = useState('');
const [lastName, setLAstName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

,然后为每个组件设置一个不同的函数来更改状态,而不是在类组件中设置一个函数handleChange

const handleFirstNameChange = (e) => {
  setFirstName(e.target.value)
}

const handleFirstNameChange = (e) => {
  setLastName(e.target.value)
}

const handleEmailChange= (e) => {
  setEmail(e.target.value)
}

const handlePasswordChange= (e) => {
  setPassword(e.target.value)
}

这很冗长,有没有办法使用钩子在经典组件中实现相同的东西?

3 个答案:

答案 0 :(得分:3)

使用功能组件时,您不需要将状态分为多个状态,尤其是在按某种方式使用表单时,只需执行以下操作即可:

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';


const SignUp = () => {
  const [state, setState] = React.useState({
      firstName: '',
      lastName: '',
      email: '',
      password: '',
   })

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

   const handleSubmit = () => {
     console.log(state);
   }

   return (
     <form onSubmit={handleSubmit}>
         <h5>Sign Up</h5>

          <div className="input-field">
              <label htmlFor="firstName">First Name</label>
              <input type="text" id="firstName" onChange={handleChange}/>
         </div>

         <div className="input-field">
             <label htmlFor="lastName">Last name</label>
             <input type="text" id="lastName" onChange={handleChange}/ >
         </div>

         <div className="input-field">
            <label htmlFor="email">Email</label>
            <input type="email" id="email" onChange={handleChange} />
         </div>

         <div className="input-field">
             <label htmlFor="password">Password</label>
             <input type="password" id="password" onChange={handleChange} />
         </div>

         <button className="btn pink z-depth-0 lighten-1 text-grey">Sign up</button>
     </form>
  )
}

render(<SignUp />, document.getElementById('root'));

我刚刚为电子邮件和assword jsx节点添加了丢失的ID,并将状态更改为使用useState,但是保留了之前在类组件中定义的形状。这样,您无需进行太多更改即可使其像以前一样工作。

请参见this repro on Stackblitz

答案 1 :(得分:2)

只需将一个对象存储在您的React.usState中即可:

const [formData, setFormData] = useState({
      firstName: '',
      lastName: '',
      email: '',
      password: '',
   });

然后对您的handleChange函数使用相同的逻辑:

function handleChange(e) {
  setFormData({ ...formData, [e.target.id]: e.target.value })
}

答案 2 :(得分:2)

您可以使用useReducer:

import React, { useReducer } from "react";

const SignUp = () => {
  function reducer(currentState, newState) {
    return { ...currentState, ...newState };
  }

  const [{ firstName, lastName, email, password }, setState] = useReducer(
    reducer,
    {
      firstName: "",
      lastName: "",
      email: "",
      password: ""
    }
  );

  const handleSubmit = event => {
    event.preventDefault();
    console.log("firstName: ", firstName);
    console.log("lastName: ", lastName);
    console.log("email: ", email);
    console.log("password: ", password);
  };

  return (
    <form onSubmit={handleSubmit}>
      <h5>Sign Up</h5>

      <div className="input-field">
        <label htmlFor="firstName">First Name</label>
        <input
          type="text"
          value={firstName}
          id="firstName"
          onChange={e => setState({ firstName: e.target.value })}
        />
      </div>

      <div className="input-field">
        <label htmlFor="lastName">Last Name</label>
        <input
          type="text"
          value={lastName}
          id="lastName"
          onChange={e => setState({ lastName: e.target.value })}
        />
      </div>

      <div className="input-field">
        <label htmlFor="email">Email</label>
        <input
          type="email"
          value={email}
          onChange={e => setState({ email: e.target.value })}
        />
      </div>

      <div className="input-field">
        <label htmlFor="password">Password</label>
        <input
          type="password"
          value={password}
          onChange={e => setState({ password: e.target.value })}
        />
      </div>

      <button className="btn pink z-depth-0 lighten-1 text-grey">
        Sign up
      </button>
    </form>
  );
};

export default SignUp;

https://codesandbox.io/s/serene-margulis-wz8ge