Bookmarks MERN
Building A Simple Full Crud MERN App
Form Handling
There are two ways to handle forms in React.
Controlled Forms: The value of the inputs are bound to state, so value of state and the value of the inputs are always in sync.
Uncontrolled Forms: The forms are not bound by state, instead their values are pulled using a ref when needed.
Example of a Controlled Form
Parts:
- object holding form values as state
- handleChange function that updates the state when we type into the form
- handleSubmit function to handle form submission and do what you want with the data
import { useState } from "react"
export default function Form(props) {
//State to hold the form data
const [form, setForm] = useState({
name: "",
age: 0,
})
// handleChange function
const handleChange = event => {
// dynamically update the state using the event object
// this function always looks the same
setForm({ ...form, [event.target.name]: event.target.value })
}
const handleSubmit = event => {
// prevent page refresh
event.preventDefault()
// do what you want with the form data
console.log(form)
}
// The JSX for the form binding the functions and state to our inputs
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={form.name}
onChange={handleChange}
name="name"
placeholder="write name here"
/>
<input
type="number"
value={form.age}
onChange={handleChange}
name="age"
placeholder="write age here"
/>
<input type="submit" value="Submit Form" />
</form>
)
}
Example of an Uncontrolled Form
- a ref created for each input
- handleSubmit for when form is submitted
import { useRef } from "react"
export default function Form(props) {
// ref to get input values
const nameInput = useRef(null)
const ageInput = useRef(null)
const handleSubmit = event => {
// prevent page refresh
event.preventDefault()
// do what you want with the form data
console.log({
name: nameInput.current.value,
age: ageInput.current.value,
})
}
// The JSX for the form binding the functions and state to our inputs
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={nameInput} placeholder="write name here" />
<input type="number" ref={ageInput} placeholder="write age here" />
<input type="submit" value="Submit Form" />
</form>
)
}
Part 1 Making The API & Connecting it to a React App
URL | HTTP Verb | Action |
---|---|---|
/api/bookmarks/:id | DELETE | destroy bookmark |
/api/bookmarks/:id | PUT | update bookmark |
/api/bookmarks | POST | create bookmark |
/api/users/login | POST | Login User |
/api/users/ | POST | Sign Up User |
/api/users/bookmarks | GET | Get Users Bookmarks |
User
name
email
password
bookmarks ref of bookmarks
Bookmark
title
link
Steps
- Use Create React App to Build App
- Add .env, server.js, .env.example, Models, Controllers, Routes and Config Folders
- Add Mongoose, Morgan, Bcrypt and Jsonwebtoken
- Build Server and config/database
- Build Bookmark Model and User Model
- Build Controllers for Bookmark and User
- Build Router For Bookmarks and User
- Test Login, SignUp, CreateBookmark, ListBookmarksByUser, DeleteBookmark, UpdateBookmark
Part 2 Using Components to Properly Separate Concerns
Steps
- Login, SignUp, CreateBookmark, ListBookmarksByUser, DeleteBookmark, UpdateBookmark Functionality
- Login/SignUp Page and functionality
- BookmarksPage
- CreateBookmark Component and use
UseRef for form
- Verify created bookmarks get added to list
- BookmarkList Component
- When Bookmark gets clicked it opens up Bookmark in a new tab
- Bookmark Component
- Update & Delete Bookmark Functionality applied
- Delete Via Button
- Update Via Conditionally Rendering Input Field Adding New Text and pressing enter
{ showUpdateInput ?
<input type='text' defaultValue={bookmark.title} onKeyPress={(e) => e.key === 'Enter' && updateBookmark(e, bookmark._id, setShowUpdateInput) }/>:
<span onClick={() => setShowUpdateInput(true)}>{bookmark.title}</span>}
Part 3 Using CSS Modules to Properly Style Components
Steps
- Add Sass
- Style Login/SignUp Page
- Style Bookmark
- Style BookmarkList
- Create Universal Body Styling