简体   繁体   中英

How to make onChange tracking function in functional component as in class component

Here is my class component

handleChange =(e) => {
   this.setState({
       [e.target.id]: e.target.value
   })
}

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

As you can see we can track all the input with one function component.

But how to get the same result as that inside the functional component? Now I am setting state for each element.

<div className="input-field">
          <label htmlFor="email">Email</label>
          <input type="email" id="email" onChange={e =>setEmail(e.target.value)}/>
       </div>
 <div className="input-field">
          <label htmlFor="password">Password</label>
          <input type="password" id="password" onChange={e => setPassword(e.target.value)}/>
 </div>

The update is similar. Given some state, data for example, then a handler may look like:

const handleChange = (e) => {
  const { id, value } = e.target;
  setData((data) => ({
    ...data,
    [id]: value
  }));
};

Use a functional state update to spread in the existing state and use the input's id and value from the onChange event to update that section of state.

编辑 how-to-make-onchange-tracking-function-in-functional-component-as-in-class-compo

Full code example

function App() {
  const [data, setData] = useState({});

  const handleChange = (e) => {
    const { id, value } = e.target;
    setData((data) => ({
      ...data,
      [id]: value
    }));
  };

  return (
    <div className="App">
      <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>

      <div>Email: {data.email}</div>
      <div>Password: {data.password}</div>
    </div>
  );
}
const [input, setInput] = useState({email:"", password:""})

<div className="input-field">
            <label htmlFor="email">Email</label>
            <input type="email" id="email" value={input.email} 
            onChange={e => setInput({...input,[e.target.id]: e.target.value}}/>
 </div>
 <div className="input-field">
            <label htmlFor="password">Password</label>
            <input type="password" id="password" value={input.password} 
             onChange={e => setInput({...input,[e.target.id]: e.target.value}}/>
 </div>

You can try this code. In this way you can handle both inputs using same state without handler

declare one state containing both email and pasword for your functional component as below :

let [loginInfo, setLoginInfo] = useState({email:'',password:''})

handleChange =(e) => {
    setLoginInfo({
       ...loginInfo,
       [e.target.id]: e.target.value
    })    

}

you form

<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>

You can create object of form input and assign it to a state like below

const [formInput, setFormInput] = useState({
    email: "",
    password: ""
  });

And set it like this

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

See this codesandbox code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM