How To Create Forms In React ? - Controlled Inputs & Material UI
Tags: react, javascript, css, html
Published: 2021-05-27 13:39:01

Hi guys, Today we are going to build a simple form which take input from user and we log the data in console. We gonna build reusable inputs, which makes our code look clean and easy to build forms.  

**so let's start coding...**

**Demo Video**
{%youtube IdzWiD2_COI %}
[Source Code](https://github.com/sk-Jahangeer/react-forms)

**Project Structure**
![react-forms-project-structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8gc3hk5gsdf5vz5alk4.png)

**Create a New React App**
```javascript
npx create-react-app react-forms
cd react-forms
npm start
```
I'am using **material-ui/core** package, It is optional . If you wanna follow along with me install this package by this command.
```javascript
npm install @material-ui/core
```
**App.css**
```css
.App {
    width: 100vw;
    height: 100vh;
    background-color: #f5f5f5;
}

.flex {
    display: flex;
    justify-content: center;
    align-items: center;
}

.column {
    flex-direction: column;
}

.form {
    display: flex;
    flex-direction: column;
    width: 350px;
    padding: 10px;
}

.input {
    width: 100% !important;
    margin: 5px 0 !important;
}
```

**Create textInput component**

/src/components/common/textInput.js
```javascript
import TextField from "@material-ui/core/TextField";

const TextInput = ({ ...rest }) => {
    return (
        <TextField
            variant="outlined"
            size="small"
            className="input"
            {...rest}
        />
    );
};

export default TextInput;
```
**...rest** = You're simply pulling off the rest of the properties defined on your **props** object into a new argument called **rest**.

**Create selectInput component**

/src/components/common/selectInput.js
```javascript
import TextField from "@material-ui/core/TextField";

const SelectInput = ({ options, ...rest }) => {
    return (
        <TextField
            variant="outlined"
            size="small"
            className="input"
            select
            {...rest}
            SelectProps={{ native: true }}
        >
            <option defaultValue="" style={{ display: "none" }}></option>
            {options.map((option) => (
                <option key={option} value={option}>
                    {option}
                </option>
            ))}
        </TextField>
    );
};

export default SelectInput;
```
**Create radioInput component**

/src/components/common/radioInput.js
```javascript
import Radio from "@material-ui/core/Radio";
import RadioGroup from "@material-ui/core/RadioGroup";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormLabel from "@material-ui/core/FormLabel";

const RadioInput = ({ label, options, required, ...rest }) => {
    return (
        <div style={{ justifyContent: "space-between" }} className="flex input">
            <FormLabel component="legend">{label}</FormLabel>
            <RadioGroup {...rest} row>
                {options.map((option) => (
                    <FormControlLabel
                        value={option}
                        control={<Radio color="primary" required={required} />}
                        label={option}
                        key={option}
                    />
                ))}
            </RadioGroup>
        </div>
    );
};

export default RadioInput;
```
**Create form component**

/src/components/common/form.js
```javascript
import React, { Component } from "react";
import Button from "@material-ui/core/Button";
import TextInput from "./textInput";
import RadioInput from "./radioInput";
import SelectInput from "./selectInput";

class Form extends Component {
    state = { data: {} };

    handleChange = ({ currentTarget: input }) => {
        const data = { ...this.state.data };
        data[input.name] = input.value;
        this.setState({ data });
    };

    handleSubmit = (event) => {
        event.preventDefault();
        this.doSubmit();
    };

    renderTextInput(name, label, type = "text", required = true) {
        const { data } = this.state;
        return (
            <TextInput
                name={name}
                value={data[name]}
                type={type}
                required={required}
                label={label}
                onChange={this.handleChange}
            />
        );
    }

    renderRadioInput(name, label, options, required = true) {
        const { data } = this.state;
        return (
            <RadioInput
                name={name}
                value={data[name]}
                onChange={this.handleChange}
                label={label}
                options={options}
                required={required}
            />
        );
    }

    renderSelectInput(name, label, options, required = true) {
        const { data } = this.state;
        return (
            <SelectInput
                name={name}
                value={data[name]}
                options={options}
                label={label}
                required={required}
                onChange={this.handleChange}
            />
        );
    }

    renderSubmitBtn(name) {
        return (
            <Button
                type="submit"
                style={{ marginLeft: "auto" }}
                variant="contained"
                size="medium"
                color="primary"
            >
                {name}
            </Button>
        );
    }
}

export default Form;
```
**Create profile component**

/src/components/profile.js
```javascript
import React from "react";
import Form from "./common/form";
import Card from "@material-ui/core/Card";

class Profile extends Form {
    state = {
        data: { name: "", email: "", status: "", gender: "" },
    };

    doSubmit = () => {
        console.log(this.state.data);
    };

    render() {
        return (
            <div className="flex column">
                <h1>Profile</h1>
                <form onSubmit={this.handleSubmit}>
                    <Card className="form">
                        {this.renderTextInput("name", "Name")}
                        {this.renderTextInput("email", "Email", "email")}
                        {this.renderSelectInput("status", "Marital Status", [
                            "Single",
                            "Married",
                            "Divorced",
                            "Widowed",
                        ])}
                        {this.renderRadioInput("gender", "Gender", [
                            "Male",
                            "Female",
                            "Other",
                        ])}
                        {this.renderSubmitBtn("Submit")}
                    </Card>
                </form>
            </div>
        );
    }
}

export default Profile;
```
**App.js**
```javascript
import Profile from "./components/profile";
import "./App.css";

function App() {
    return (
        <div className="App flex">
            <Profile />
        </div>
    );
}

export default App;
```
That's it test the form in browser, If you found any mistakes or making code better let me know in comment. For better understanding please watch Youtube video. Subscribe to my Youtube channel to get more knowledgeable content every week. 

**Arigato Gozaimasu.. 🙂**