Signup component 

The Signup component in client/user/Signup.js, presents a form with name, email, and password fields to the user for sign-up at the '/signup' path:

In the component definition, we first initialize the state with empty input field values, empty error message, and set the dialog open variable to false.

mern-skeleton/client/user/Signup.js:

  constructor() {
state = { name: '', password: '', email: '', open: false, error: '' }
...

We also define two handler functions to be called when the input value changes or the submit button is clicked. The handleChange function takes the new value entered in the input field and sets it to state.

mern-skeleton/client/user/Signup.js:

handleChange = name => event => {
this.setState({[name]: event.target.value})
}

The clickSubmit function is called when the form is submitted. It takes the input values from state and calls the create fetch method to sign up the user with the backend. Then, depending on the response from the server, either an error message is shown or a success dialog is shown.

mern-skeleton/client/user/Signup.js:

  clickSubmit = () => {
const user = {
name: this.state.name || undefined,
email: this.state.email || undefined,
password: this.state.password || undefined
}
create(user).then((data) => {
if (data.error)
this.setState({error: data.error})
else
this.setState({error: '', open: true})
})
}

In the render function we compose and style the form components in the Sign-up view using components such as TextField from Material-UI.

mern-skeleton/client/user/Signup.js:

  render() {
const {classes} = this.props
return (<p>
<Card className={classes.card}>
<CardContent>
<Typography type="headline" component="h2"
className={classes.title}>
Sign Up
</Typography>
<TextField id="name" label="Name"
className={classes.textField}
value={this.state.name}
onChange={this.handleChange('name')}
margin="normal"/> <br/>
<TextField id="email" type="email" label="Email"
className={classes.textField} value=
{this.state.email}
onChange={this.handleChange('email')}
margin="normal"/><br/>
<TextField id="password" type="password"
label="Password" className={classes.textField}
value={this.state.password}
onChange={this.handleChange('password')}
margin="normal"/><br/>
{this.state.error && ( <Typography component="p"
color="error">
<Icon color="error"
className={classes.error}>error</Icon>
{this.state.error}</Typography>)}
</CardContent>
<CardActions>
<Button color="primary" raised="raised"
onClick={this.clickSubmit}
className={classes.submit}>Submit</Button>
</CardActions>
</Card>
<Dialog> ... </Dialog>
</p>)
}

The render also contains an error message block along with a Dialog component that is conditionally rendered depending on the sign up response from the server. The Dialog component in Signup.js is composed as follows.

mern-skeleton/client/user/Signup.js:

<Dialog open={this.state.open} disableBackdropClick={true}>
<DialogTitle>New Account</DialogTitle>
<DialogContent>
<DialogContentText>
New account successfully created.
</DialogContentText>
</DialogContent>
<DialogActions>
<Link to="/signin">
<Button color="primary" autoFocus="autoFocus" variant="raised">
Sign In
         </Button>
</Link>
</DialogActions>
</Dialog>

On successful account creation, the user is given confirmation, and asked to sign in using this Dialog component, which links to the Signin component:

To add the Signup component to the app, add the following Route to the MainRouter in the Switch component.

mern-skeleton/client/MainRouter.js:

<Route path="/signup" component={Signup}/>

This will render the Signup view at '/signup'.