React JS Application | Authentication UI & Handling Forms| Part 4–30
Now we will create the authentication UI of the application. introduce the concept of retrieving data client-side within the component. The first thing we are going to do is create the <SignUp>
and <SignIn>
components.
This is not necessarily focused on security rather a way to organize the curation and creation of recipes from the users.
Let us start with the DOM hierarchy of the SignUp class component:
<SignIn>
-- <div container>
---- <form onSubmit={}>
------ <h3 >
------ <div input-feild>
--------- <label email>
--------- <input email onChange={}>
------ <div input-feild>
--------- <label email>
--------- <input email onChange={}>
------ <div input-feild>
--------- <button ?>
Now we can build it out
// SignIn.jsclass SignIn extends Component { // Intro To Helper Functions
handleChange = (e) => {
console.log(e) }
handleSubmit = (e) => {
console.log(e) } render() {
return( <div className="container">
<form onSubmit={this.handleSubmit} className="signup">
<h3 className="?">
<div className="?">
<label htmlFor="email">
<input type="email" id="password" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="password">
<input type="password" id="password" onChange={this.handleChange}>
</div>
<div className="?">
<button>Sign Up</button>
</div> </form>
</div> )
}
}
Quickly covering the code: we are using a class since we will be using the state within the component in addition to methods relative to the lifecycle of the component.
Notice we use two functions provided to us by reacting as props in the component (element) tag: onChange={} & onSubmit={}. These allow for functions as arguments and returns an object that can be used within those functions. That is where the e comes in as a parameter for the handleChange() function. This e (event) object is returning a lot of information that could be used in the function such as the given value of the specific inputs and forms once modified or complete.
Now we will make use of the even object in the functions.
// SignIn.jsclass SignIn extends Component {
state={
email: "",
password: ""}// Intro To Helper Functions
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value})}
handleSubmit = (e) => {
e.preventDefault(); // default action to reset on submit errases state atm. console.log(this.state)}render() {
return(<div className="container">
<form onSubmit={this.handleSubmit} className="signup">
<h3 className="?">
<div className="?">
<label htmlFor="email">
<input type="email" id="password" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="password">
<input type="password" id="password" onChange={this.handleChange}>
</div>
<div className="?">
<button>Sign Up</button>
</div></form>
</div>)
}
}
Now we are introducing state. The state is essentially the current state of this component. You do not want to set state manually instead use the setState({})
method. You notice we use [bracket] and dot.notation to set the state.
Remember the e variable is the event object with various attributes and methods available. Therefore, we can use the target attribute to retrieve the element being targeted (which input feild is being used) and retrieve the ID of that targeted element (field being used).
[e.target.id]: e.target.value
// e = event object returned from the onChange/onSubmit callback fn
// target = element being used
// id = the ID we assinged it in the tag eg. id="email"
// value = the value of that element at that moment when called. // bracket notation dynamically calls the attribute of the key in / // state. value reassing the value through the setState() method-- / // taking an obj as a param.
Once that is all understood and sorted we will copy & paste the code into our SignUp component just modifying the required fields
// SignUp.jsclass SignUp extends Component {
state={
email: "",
password: "",
first: "",
last: "" } // Intro To Helper Functions
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value })
} handleSubmit = (e) => {
e.preventDefault(); // default action to reset on submit errases state atm.
console.log(this.state) } render() {
return(<div className="container">
<form onSubmit={this.handleSubmit} className="signup">
<h3 className="?">
<div className="?">
<label htmlFor="email">
<input type="email" id="password" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="password">
<input type="password" id="password" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="first">
<input type="first" id="first" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="last">
<input type="last" id="last" onChange={this.handleChange}>
</div> <div className="?">
<button>Sign Up</button>
</div> </form>
</div> )
}
}
Notice the only difference? We only are adding additional fields in our state and the inputs within the form. The e.target.id system we created will still capture the new attributes in the state.
Creating the <CreateRecipe> form
This will generally follow the same form structure so you can totally copy & paste — modifying as needed:
// CreateRecipe.jsclass CreateRecipe extends Component {
state={
title: "",
recipe: "",
ingredients: ""}// Intro To Helper Functions
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value})
}handleSubmit = (e) => {
e.preventDefault(); // default action to reset on submit errases state atm.
console.log(this.state)}render() {
return(<div className="container">
<form onSubmit={this.handleSubmit} className="signup">
<h3 className="?">
<div className="?">
<label htmlFor="title">
<input type="text" id="title" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="recipe">
<textArea type="text" id="recipe" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="ingredients">
<textArea type="text" id="ingredients" onChange={this.handleChange}>
</div>
<div className="?">
<label htmlFor="last">
<input type="last" id="last" onChange={this.handleChange}>
</div><div className="?">
<button>Create</button>
</div></form>
</div>)
}
}export default CreateRecipe;
Link The Pages
Next, we will import and link to our root direction, so that when the user navigates.
// App.jsimport "./styles.css";
import NavBar from "path/NavBar";
import Dashboard from "path/Dashboard";
import RecipeDetail from "path/RecipeDetail";
import SignIn rom "path/SignIn"
import SignUp rom "path/SignUp"
import CreateRecipe rom "path/CreateRecipe"
import {BrowseRouter as Router, Route, Swtich} from "path/react-router-dom"function App() {
return(
<Router />
<div className="app">
<NavBar />
<div className="content"> <Swtich />
<Route path="/" exact /> <Dashboard /> </Route>
<Route path="/recipe/:id" /> <RecipeDetail /> </Route>
<Route path="/signin" /> <SignIn /> </Route>
<Route path="/signin" /> <SignIn /> </Route>
<Route path="/createrecipe" /> <CreateRecipe /> </Route>
<Swtich />
</div>
</div>
</Router>
)
}
on.