I thought to make a tutorial about this old project of mines, becouse thinking about it today I so like how simple it is to understand, or at least how it looks to my eyes now, I hope by the end of this tutorial you can get this feeling as well. It is nothing too complicated what we are going to build and we will not trigger any real function, but we are not far away from a real solution. And then you know, what's better than reading React and Material-ui? This is what we are going to build
This project was bootrapped with the create-react-app
boilerplate, to get started create a new folder and open it up with VS code, in your terminal type npx create-react-app my-multi-step-form
. You can delete what you don't need, and keep going. Create a folder called components
in which
we are going to have our 5 main operation stored in a .js file. The thing here is wrapping your head around material-ui naming conventions a little bit, you know what I mean, there is nothing wrong with it, it is a good UI framework. We will now create the components we are going to use to make our main component UserForm.js
work. The first component we are going to create we will name it FormUserDetails.js
and will look something like this
import React, { Component } from "react";
import Dialog from "@material-ui/core/Dialog";
import AppBar from "@material-ui/core/AppBar";
import { ThemeProvider as MuiThemeProvider } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
export class FormUserDetails extends Component {
continue = (e) => {
e.preventDefault();
this.props.nextStep();
};
render() {
const { values, handleChange } = this.props;
return (
<MuiThemeProvider>
<>
<Dialog open fullWidth maxWidth="sm">
<AppBar title="Enter User Details" />
<TextField
placeholder="Enter Your First Name"
label="First Name"
onChange={handleChange("firstName")}
defaultValue={values.firstName}
margin="normal"
fullWidth
/>
<br />
<TextField
placeholder="Enter Your Last Name"
label="Last Name"
onChange={handleChange("lastName")}
defaultValue={values.lastName}
margin="normal"
fullWidth
/>
<br />
<TextField
placeholder="Enter Your Email"
label="Email"
onChange={handleChange("email")}
defaultValue={values.email}
margin="normal"
fullWidth
/>
<br />
<Button color="primary" variant="contained" onClick={this.continue}>
Continue
</Button>
</Dialog>
</>
</MuiThemeProvider>
);
}
}
export default FormUserDetails;
Next component is going to be called FormPersonalDetails.js
and is going to receive other information from the user
import React, { Component } from "react";
import Dialog from "@material-ui/core/Dialog";
import AppBar from "@material-ui/core/AppBar";
import { ThemeProvider as MuiThemeProvider } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
export class FormPersonalDetails extends Component {
continue = (e) => {
e.preventDefault();
this.props.nextStep();
};
back = (e) => {
e.preventDefault();
this.props.prevStep();
};
render() {
const { values, handleChange } = this.props;
return (
<MuiThemeProvider>
<>
<Dialog open fullWidth maxWidth="sm">
<AppBar title="Enter Personal Details" />
<TextField
placeholder="Enter Your Occupation"
label="Occupation"
onChange={handleChange("occupation")}
defaultValue={values.occupation}
margin="normal"
fullWidth
/>
<br />
<TextField
placeholder="Enter Your City"
label="City"
onChange={handleChange("city")}
defaultValue={values.city}
margin="normal"
fullWidth
/>
<br />
<TextField
placeholder="Enter Your Bio"
label="Bio"
onChange={handleChange("bio")}
defaultValue={values.bio}
margin="normal"
fullWidth
/>
<br />
<Button color="secondary" variant="contained" onClick={this.back}>
Back
</Button>
<Button color="primary" variant="contained" onClick={this.continue}>
Continue
</Button>
</Dialog>
</>
</MuiThemeProvider>
);
}
}
export default FormPersonalDetails;
Last step of the operation, usually before submitting every multi step form is confirming the details you entered, also this is where you would normally do your calls to the back end so that you
could actually submit the data to do
something but we're not going to do that
this is strictly front end, create a component called Confirm.js
import React, { Component } from "react";
import Dialog from "@material-ui/core/Dialog";
import AppBar from "@material-ui/core/AppBar";
import { ThemeProvider as MuiThemeProvider } from "@material-ui/core/styles";
import { List, ListItem, ListItemText } from "@material-ui/core/";
import Button from "@material-ui/core/Button";
export class Confirm extends Component {
continue = (e) => {
e.preventDefault();
// PROCESS FORM //
this.props.nextStep();
};
back = (e) => {
e.preventDefault();
this.props.prevStep();
};
render() {
const {
values: { firstName, lastName, email, occupation, city, bio },
} = this.props;
return (
<MuiThemeProvider>
<>
<Dialog open fullWidth maxWidth="sm">
<AppBar title="Confirm User Data" />
<List>
<ListItem>
<ListItemText primary="First Name" secondary={firstName} />
</ListItem>
<ListItem>
<ListItemText primary="Last Name" secondary={lastName} />
</ListItem>
<ListItem>
<ListItemText primary="Email" secondary={email} />
</ListItem>
<ListItem>
<ListItemText primary="Occupation" secondary={occupation} />
</ListItem>
<ListItem>
<ListItemText primary="City" secondary={city} />
</ListItem>
<ListItem>
<ListItemText primary="Bio" secondary={bio} />
</ListItem>
</List>
<br />
<Button color="secondary" variant="contained" onClick={this.back}>
Back
</Button>
<Button color="primary" variant="contained" onClick={this.continue}>
Confirm & Continue
</Button>
</Dialog>
</>
</MuiThemeProvider>
);
}
}
export default Confirm;
And also you would want the Success.js
component
import React, { Component } from "react";
import Dialog from "@material-ui/core/Dialog";
import AppBar from "@material-ui/core/AppBar";
import { ThemeProvider as MuiThemeProvider } from "@material-ui/core/styles";
export class Success extends Component {
continue = (e) => {
e.preventDefault();
// PROCESS FORM //
this.props.nextStep();
};
back = (e) => {
e.preventDefault();
this.props.prevStep();
};
render() {
return (
<MuiThemeProvider>
<>
<Dialog open fullWidth maxWidth="sm">
<AppBar title="Success" />
<h1>Thank You For Your Submission</h1>
<p>You will get an email with further instructions.</p>
</Dialog>
</>
</MuiThemeProvider>
);
}
}
export default Success;
Last and most important is going to be the UserForm.js
component, were the actual state is.
import React, { Component } from "react";
import { render } from "react-dom";
import { FormUserDetails } from "./FormUserDetails";
import FormPersonalDetails from "./FormPersonalDetails";
import Confirm from "./Confirm";
import Success from "./Success";
export class UserForm extends Component {
state = {
step: 1,
firstName: "",
lastName: "",
email: "",
occupation: "",
city: "",
bio: "",
};
//Proceed to the next step
nextStep = () => {
const { step } = this.state;
this.setState({
step: step + 1,
});
};
// go back to previous step
prevStep = () => {
const { step } = this.state;
this.setState({
step: step - 1,
});
};
//handle fields change
handleChange = (input) => (e) => {
this.setState({ [input]: e.target.value });
};
render() {
const { step } = this.state;
const { firstName, lastName, email, occupation, city, bio } = this.state;
const values = {
firstName,
lastName,
email,
occupation,
city,
bio,
};
switch (step) {
case 1:
return (
<FormUserDetails
nextStep={this.nextStep}
handleChange={this.handleChange}
values={values}
/>
);
case 2:
return (
<FormPersonalDetails
nextStep={this.nextStep}
prevStep={this.prevStep}
handleChange={this.handleChange}
values={values}
/>
);
case 3:
return (
<Confirm
nextStep={this.nextStep}
prevStep={this.prevStep}
values={values}
/>
);
case 4:
return <Success />;
}
}
}
export default UserForm;
Take everything in you App.js
like so
import React from "react";
import { UserForm } from "./components/UserForm";
const App = () => {
return (
<div className="App">
<UserForm />
</div>
);
};
export default App;
Check out the repo here
Merry Christmas ☃️☃️🎄🎄