Search code examples
reactjsbootstrap-5react-bootstrap

set different hooks in react without duplicating code?


I am learning typescript + react. I have the following form using reactjs and boostrap:


function ControlGroup(props: ControlGroupProps) {
  const [agentSettings, setAgentSettings] = useState("");
  const [agentQuestion, setAgentQuestion] = useState("");

  return (
    <Form
      onSubmit={(event) =>
        props.onAskAgent(props.agentData, agentSettings, agentQuestion, event)
      }
    >
      <Form.Group className="mb-3" controlId="agentForm.settings">
        <Form.Label>Set your agent settings</Form.Label>
        <Form.Control
          as="textarea"
          rows={3}
          onChange={({ target: { value } }) => setAgentSettings(value)}
          value={agentSettings}
        />
      </Form.Group>
      <Form.Group className="mb-3" controlId="agentForm.question">
        <Form.Label> Ask your question </Form.Label>
        <Form.Control
          as="textarea"
          rows={3}
          onChange={({ target: { value } }) => setAgentQuestion(value)}
          value={agentQuestion}
        />
      </Form.Group>
      <Button className="center" type="submit">
        Ask agent
      </Button>
    </Form>
  );
}

I have two different things I need to capture, agentSettings and agentQuestion. The code below works but I don't like how I have to type:

{({ target: { value } }) => setAgentSettings(value)} and then {({ target: { value } }) => setAgentQuestion(value)}

The code is almost identical other than the last bit. Is there a more elegant way to do this in react?


Solution

  • Valid question. Especially, when there are 10 input fields, you don't want to write the same code 10 times.

    What's considered "standard" in this case is to use an object for storing form values and use one event handler for all input field changes, by using name attribute.

    Something like this:

    const [formData, setFormData] = useState({
      inputA: '',
      inputB: '',
    });
    
    ...
    
    const handleChange = (e) => {
      setFormData({
        ...formData,
        [e.target.name]: e.target.value,
      };
    };
    
    
    ...
    <input name="inputA" value={formData.inputA} onChange={handleChange} />