Skip to content

React Forms

Overview

Since React is using one way data binding - you cannot update anything on form inputs. React immediately sets the value back to initial state. So form fields need to be binded against state. And state updated on form field events

https://reactjs.org/docs/forms.html

Components

  • View component
  • Possible input values
  • Callback function
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from 'react';

interface IProps {
    values: {
    input: string;
    checkbox: boolean;
    select: string;
    radio1: boolean;
    radio2: boolean;
    textarea: string;
}

handleChange: (target: 
    EventTarget & HTMLInputElement | 
    EventTarget & HTMLSelectElement | 
    EventTarget & HTMLTextAreaElement) => void;
}

const FormView = (props: IProps) => {
    return (
        <form>
            // Code omitted

Example of react form

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<form>
    <div className="form-group">
        <label htmlFor="exampleInputEmail1">Email</label>
        <input value={props.values.input} onChange={(e) => props.handleChange(e.target)} name="input" type="text" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" />
    </div>
    <div className="form-group form-check">
        <input checked={props.values.checkbox} onChange={(e) => props.handleChange(e.target)} name="checkbox" type="checkbox" className="form-check-input" id="exampleCheck1" />
        <label className="form-check-label" htmlFor="exampleCheck1">Check me out</label>
    </div>
    <div className="form-group">
        <label htmlFor="exampleFormControlSelect1">Example select</label>
        <select value={props.values.select} onChange={(e) => props.handleChange(e.target)} name="select" className="form-control" id="exampleFormControlSelect1">
            <option value="1">1</option>
            <option value="2">2</option>
        </select>
    </div>
    <div className="form-check form-check-inline">
        <input checked={props.values.radio1} onChange={(e) => props.handleChange(e.target)} name="radio" value="radio1" className="form-check-input" type="radio" id="inlineRadio1" />
        <label className="form-check-label" htmlFor="inlineRadio1">1</label>
    </div>
    <div className="form-check form-check-inline">
        <input checked={props.values.radio2} onChange={(e) => props.handleChange(e.target)} name="radio" value="radio2" className="form-check-input" type="radio" id="inlineRadio2" />
        <label className="form-check-label" htmlFor="inlineRadio2">2</label>
    </div>
    <div className="form-group">
        <label htmlFor="exampleFormControlTextarea1">Example textarea</label>
        <textarea value={props.values.textarea} onChange={(e) => props.handleChange(e.target)} name="textarea" className="form-control" id="exampleFormControlTextarea1" rows={3} />
    </div>
</form>

Control component - state

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import React, { useState, useEffect } from 'react';
import FormView from './FormView';

const Form = () => {
    const [values, setInput] = useState({
        input: "foo",
        checkbox: true,
        select: "2",
        radio1: false,
        radio2: true,
        textarea: "foo\nbar",
    });

    // Code omitted
}

Control component - callback function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const handleChange = (target:
    EventTarget & HTMLInputElement |
    EventTarget & HTMLSelectElement |
    EventTarget & HTMLTextAreaElement) => {
    //debugger;
    console.log(target.name, target.value, target.type, target)

    if (target.type === "text") {
        setInput({ ...values, [target.name]: target.value });
        return;
    }
    if (target.type === "checkbox") {
        setInput({ ...values, [target.name]: (target as EventTarget & HTMLInputElement).checked });
        return;
    }
    if (target.type === "radio" && target.name === "radio") {

    if (target.value === "radio1") {
        setInput({ ...values, radio1: true, radio2: false });
        return;
    }
        setInput({ ...values, radio1: false, radio2: true });
        return;
    }
    setInput({ ...values, [target.name]: target.value });
};

Control component - passing callback

Pass the state and value update callback function to form view.

1
2
3
4
5
    // Code omitted

    return <FormView values={values} handleChange={handleChange} />
}
export default Form;