Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Hooks: handle multiple inputs

on react docs forms section there is the following example using class components:

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

Considering Hooks can only be called either in a React function component or a custom React Hook function is there a way of doing it using hooks instead?

like image 620
nishi Avatar asked Sep 02 '20 17:09

nishi


People also ask

How do you handle multiple events in React?

Call a Function onClick in React The first solution to perform multiple onClick events in React is to include all of your actions inside of a function and then call that single function from the onClick event handler.

Is it possible to call hooks from a react function?

Considering Hooks can only be called either in a React function component or a custom React Hook function is there a way of doing it using hooks instead? Show activity on this post.

How do you handle multiple inputs in a form?

When creating a form with React components, it is common to use an onChange handler to listen for changes to input elements and record their values in state. Besides handling just one input, a single onChange handler can be set up to handle many different inputs in the form.

What is uncontrolled input in react JS?

With React, we use javascript to handle the way we get access to the data entered by the users. In HTML, form types such as <input> <textarea> generally handle their own state and update based on user input. letting the DOM handle user input for you is referred to as uncontrolled input.

What happens to the form on subsequent user input in react?

Hence, the React component that renders the form is now in control of what happens to that form on subsequent user input. In most scenarios, we will be needing more than one input field from users. To demonstrate this, let’s create a registration form.


3 Answers

you can clean up @adam 's final solution a bit by not using the useCallback hook, and instead simply using the useState hook as a controlled component.

const MyComponent = () => {
   const [inputs, setInputs] = useState({});
   const handleChange = e => setInputs(prevState => ({ ...prevState, [e.target.name]: e.target.value }));

   return (
     <> 
      <input name="field1" value={inputs.field1 || ''} onChange={handleChange} />
      <input name="field2" value={inputs.field2 || ''} onChange={handleChange} />
     </>
   )
}
like image 142
Ian Rios Avatar answered Oct 18 '22 21:10

Ian Rios


example

const MyComponent = () => {
   const [inputs,setInputs] = useState({});

   return (
     <> 
      <input key="field1" name="field1" onChange={({target}) => setInputs(state => ({...state,field1:target.value}))} value={inputs.field1}/>
      <input key="field2" name="field2" onChange={({target}) => setInputs(state => ({...state,field2:target.value}))} value={inputs.field2}/>
     </>
   )

}

you can pass in initial values like this:

const MyComponent = (initialValues = {}) => {
   const [inputs,setInputs] = useState(initialValues);
   ...
}

EDIT: A nice short onChange according to @hamidreza's comment

const MyComponent = (initialValues = {}) => {
   const [inputs,setInputs] = useState(initialValues);
   const onChangeHandler = useCallback(
     ({target:{name,value}}) => setInputs(state => ({ ...state, [name]:value }), [])
   );

   return (
     <> 
      <input key="field1" name="field1" onChange={onChangeHandler} value={inputs.field1}/>
      <input key="field2" name="field2" onChange={onChangeHandler} value={inputs.field2}/>
     </>
   )


}

etc, etc, etc

like image 39
Adam Avatar answered Oct 18 '22 21:10

Adam


Maybe, on the last example onChangeForField('...') will be triggered on each render, so maybe you have to write onChange={()=>onChangeForField('...')} or if you want the event to get passed onChange={(e)=>onChangeForField('...', e)}

like image 2
JB_DELR Avatar answered Oct 18 '22 20:10

JB_DELR