• Stars
    star
    328
  • Rank 123,532 (Top 3 %)
  • Language
    JavaScript
  • Created almost 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Contact manager using React hooks & context

Contact Keeper

Full stack MERN contact manager with React hooks, context & JWT authentication. Part of my React course on Udemy.

The app has been refactored since the course to take a more hook orientated approach and to use React Router 6.

At the time of the course hooks were very new and much of their implementation tried to substitute lifecycle methods with the closest hooks approximation which is understandable, many tutorials and courses early to adopt hooks took this approach. Hooks were very new at the time of recording, as more clearly defined patterns of use have emerged it's clear that hooks require a completely different approach and thought process to lifecycle methods. We need to think in terms of hooks and functions and not lifecycle.

If you are looking for the code you will see in the Udemy course then please check out the originalcoursecode branch of this repository.

If you're looking to fix your course code or wondering why in the course we had to use // eslint-disable-next-line or thought this doesn't feel right ignoring the linting rules, then I urge you to have a read of this post on overreacted by Dan Abramov. It covers a lot more than just useEffect There is also this great article from Kent C. Dodds. And this excellent full explanation of useEffect on the LogRocket blog.

To summarize the issues we faced in the course though, and why we had to use // eslint-disable-next-line at all is that all our data fetching methods are in our context states (AuthState.js and ContactState.js) and passed down to all our components via the context Provider. The problem with this is that every time we update our context state we create a new function. If we include these functions in our useEffect dependency array (as the linter suggests) then each time we fetch data and our reducer runs it updates the context which triggers a re-render (creating a whole set of new functions). The useEffect dependency sees it as a new function and triggers another render which again updates the state when we call the function in our useEffect, which triggers another re-render and so on.... infinite loop of re-rendering. Even though these functions are called the same and do the same thing, in memory they are different functions.

The solution is not to add an empty array and tell the linter to ignore it (trying to make a componentDidMount out of useEffect), but to think in terms of hooks and functions. We should keep our functions pure where possible and take all our data fetching methods out of context state. Take a look at ContactState.js as an example. You will see all of our action creators have been taken out of the context, this gurantees that the functions never change with a update to state and don't need to be added to the dependency array in useEffect. Each function now takes a dispatch argument as the first parameter which is passed in at the time of invocation. We can safely provide the dispatch via our context as react gurantees that a dispatch returned from useReducer is static and won't change. So the dispatch in our context state will not be a problem. Here is our new getContacts function:

export const getContacts = async (dispatch) => {
  try {
    const res = await axios.get('/api/contacts');

    dispatch({
      type: GET_CONTACTS,
      payload: res.data
    });
  } catch (err) {
    dispatch({
      type: CONTACT_ERROR,
      payload: err.response.msg
    });
  }
};

As you can see it takes disptach as the first argument and it is exported as a named export so we can use it.

We also make a new custom hook to easily consume our auth state and dispatch in our components..

export const useContacts = () => {
  const { state, dispatch } = useContext(ContactContext);
  return [state, dispatch];
};

We can then use our new hook like so (example taken from Contacts.js)

Import it along with our methods

import { useContacts, getContacts } from '../../context/contact/ContactState';

Use the hook to get our state and dispatch

const [contactState, contactDispatch] = useContacts();

const { contacts, filtered } = contactState;

And in our useEffect to fetch our users contacts

useEffect(() => {
  getContacts(contactDispatch);
}, [contactDispatch]);

You'll note that we did not need to include getContacts in our dependency array and we get no warnings now. We don't need to include getContacts as it doesn't change, it's the same function used every time.

Ultimately a good rule of thumb when using react context along with hooks would be to not provide functions in your context state, especially if those functions have side effects. The only exception being the dispatch returned from useReducer.

Postman Routes

Test your routes in PostMan with the following...

Users & Authentication Routes

  1. Register a new user - POST http://localhost:5000/api/users

    Headers
    key value
    Content-Type application/json

Body

{
"name": "Sam Smith",
"email": "[email protected]",
"password": "123456"
}
  1. Login a user - POST http://localhost:5000/api/auth
Headers
key value
Content-Type application/json

Body

{
"email": "[email protected]",
"password": "123456"
}
  1. Get logged in user - GET http://localhost:5000/api/auth
Headers
key value
Content-Type application/json
x-auth-token <VALID_TOKEN>

Contacts Routes

  1. Get a users contacts - GET
Headers
key value
Content-Type application/json
x-auth-token <VALID_TOKEN>
  1. Add a new contact - POST http://localhost:5000/api/contacts
Headers
key value
Content-Type application/json
x-auth-token <VALID_TOKEN>

Body

{
"name": "William Williams",
"email": "[email protected]",
"phone": "77575894"
}
  1. Update a contact - PUT http://localhost:5000/api/contacts/<CONTACT_ID>
Headers
key value
Content-Type application/json
x-auth-token <VALID_TOKEN>

Body

{
"phone": "555555"
}
  1. Delete a contact - DELETE http://localhost:5000/api/contacts/<CONTACT_ID>
Headers
key value
Content-Type application/json
x-auth-token <VALID_TOKEN>

Usage

Install dependencies

npm install
cd client
npm install

Mongo connection setup

Edit your /config/default.json file to include the correct MongoDB URI

Run Server

npm run dev     # Express & React :3000 & :5000
npm run server  # Express API Only :5000
npm run client  # React Client Only :3000

More Repositories

1

design-resources-for-developers

Curated list of design and UI resources from stock photos, web templates, CSS frameworks, UI libraries, tools and much more
56,219
star
2

50projects50days

50+ mini web projects using HTML, CSS & JS
CSS
33,285
star
3

vanillawebprojects

Mini projects built with HTML5, CSS & JavaScript. No frameworks or libraries
JavaScript
15,310
star
4

proshop_mern

Shopping cart built with MERN & Redux
JavaScript
1,979
star
5

devconnector_2.0

Social network for developers, built on the MERN stack
JavaScript
1,888
star
6

node_passport_login

Node.js login, registration and access control using Express and Passport
JavaScript
1,695
star
7

react-crash-2021

Task tracking application from the React crash course
JavaScript
1,359
star
8

chatcord

Realtime chat app with rooms
HTML
1,144
star
9

modern_js_udemy_projects

Project files for Modern JS From The Beginning course
JavaScript
1,126
star
10

traversy-js-challenges

Challenges & docs from JS Algorithms & Data Structures course
JavaScript
796
star
11

react_express_starter

Starter pack for React and Express full stack development
JavaScript
774
star
12

mern-tutorial

Goalsetter application from Youtube series
JavaScript
694
star
13

modern_portfolio

Responsive portfolio website
SCSS
681
star
14

mern_shopping_list

Shopping List built with MERN and Redux
TypeScript
594
star
15

lead_manager_react_django

Full stack app with React, Redux & Django
JavaScript
592
star
16

loruki-website

Cloud hosting website
HTML
592
star
17

laragigs

Laravel job listing app
PHP
578
star
18

storybooks

Node.js app with Google OAuth
JavaScript
548
star
19

php-crash

Code for my PHP crash course on YouTube
PHP
542
star
20

vue-crash-2021

Task Tracker project from youtube crash course
Vue
534
star
21

feedback-app

React feedback app from React course
JavaScript
522
star
22

devcamper-api

Backend for devcamper app
HTML
513
star
23

btre_project

Django real estate website
CSS
507
star
24

javascript_cardio

JavaScript challenges and problems
JavaScript
490
star
25

ui_components

Collection of HTML & CSS UI components
HTML
483
star
26

angular-crash-2021

Task tracker app from the 2021 youtube crash course
TypeScript
478
star
27

expense-tracker-react

Simple expense tracker using React hooks & context
JavaScript
478
star
28

simple_react_pagination

Frontend pagination with React
JavaScript
477
star
29

tailwind-landing-page

CSS
475
star
30

proshop-v2

ProShop ecommerce website built with MERN & Redux Toolkit
JavaScript
469
star
31

python_sandbox

Files to learn Python basics
Python
468
star
32

vanilla-parcel-boilerplate

Simple starter workflow for building vanilla js apps with Parcel
JavaScript
434
star
33

next-crash-course

Project from my Next.js crash course on YouTube
JavaScript
426
star
34

redux_crash_course

Simple implementation of Redux with React 16
JavaScript
416
star
35

node_crash_course

Files for YouTube crash course
JavaScript
397
star
36

github-finder

Search Github users - React hooks & context
JavaScript
377
star
37

bootstrap-bootcamp-website

HTML
377
star
38

react_crash_todo

React crash course files
JavaScript
371
star
39

tailwind-course-projects

Projects from my TailwindCSS course
CSS
367
star
40

vanilla-node-rest-api

REST API using Node.js without a framework
JavaScript
361
star
41

express_crash_course

Express crash course on YouTube
JavaScript
358
star
42

rust_sandbox

Fundamentals of the Rust language
Rust
357
star
43

docker-node-mongo

Sample node and mongo app that uses docker
JavaScript
357
star
44

expense-tracker-mern

Full stack expense tracker
JavaScript
356
star
45

vue_crash_todolist

Vue crash course application
Vue
351
star
46

react_redux_express_starter

Boiler plate for React/Redux applications with Express
JavaScript
336
star
47

github-finder-app

Find github users and display their info
JavaScript
336
star
48

lsapp

Laravel from scratch website/blog application
PHP
333
star
49

project-mgmt-graphql

Full stack GraphQL, Express & React app
JavaScript
325
star
50

dj-events-frontend

Next.js website to list DJ and other musical events
JavaScript
324
star
51

webpack-starter

Boilerplate for Webpack apps
JavaScript
317
star
52

vuex_todo_manager

Vuex crah course app
Vue
315
star
53

myflaskapp

Python Flask app with authentication
Python
312
star
54

hulu-webpage-clone

Hulu webpage clone
CSS
310
star
55

nodejs-openai-image

Web app that uses Node.js and OpenAI to generate images
CSS
303
star
56

nodekb

Simple knowledgebase app with Node.js, Express and MongoDB
JavaScript
303
star
57

react_step_form

Multi step form built with React and Material UI
JavaScript
302
star
58

javascript-sandbox

Sandbox from the Modern JS From The Beginning 2.0 course
JavaScript
301
star
59

house-marketplace

House marketplace built with React and FIrebase
JavaScript
297
star
60

axios-crash

Axios crash course files
JavaScript
292
star
61

laravel-sanctum-api

REST API with auth using Laravel 8 and Sanctum
PHP
282
star
62

php_rest_myblog

PHP
281
star
63

node-api-proxy-server

Proxy server to hide public API keys with rate limiting, caching
JavaScript
281
star
64

react_webpack_starter

React 16 and Webpack 4 starter pack
TypeScript
277
star
65

next-markdown-blog

Simple blog using Next and Markdown
JavaScript
276
star
66

alexis_speech_assistant

Python speech assist app
Python
270
star
67

deno-rest-api

Simple REST API using Deno and Oak
TypeScript
268
star
68

creative-agency-website

Agency website - basic HTML/CSS
HTML
266
star
69

go_crash_course

Basics of the go language
Go
264
star
70

react_file_uploader

React and Express file uploader
JavaScript
261
star
71

breaking-bad-cast

App to show cast info for breaking bad
JavaScript
251
star
72

url_shortener_service

API to shorten urls using Node, Express & MongoDB
JavaScript
247
star
73

react_native_shopping_list

React Native app from crash course
JavaScript
243
star
74

tailwind-sandbox

Sandbox used with the Tailwind From Scratch course
HTML
241
star
75

simple-electron-react

Simple boilerplate for building Electron apps with React
JavaScript
241
star
76

bookstore

Simple RESTful JSON api using Nodejs, Express and MongoDB
HTML
240
star
77

meanauthapp

Complete MEAN stack app with authentication
JavaScript
240
star
78

electron-course-files

Files and apps for Electron course
JavaScript
238
star
79

angular-crash-todolist

Simple app for Angular crash course
TypeScript
230
star
80

node_jwt_example

Example of Node JSON Web Tokens
JavaScript
221
star
81

mern-auth

MERN authentication using JWT and HTTP-Only cookie
JavaScript
219
star
82

electronshoppinglist

Shopping list desktop app built on electron
JavaScript
219
star
83

qr-code-generator

Simple Tool to Generate QR Codes
HTML
215
star
84

go_restapi

Simple RESTful API using Golang
Go
214
star
85

lyricfinder

App that finds song lyrics using React and the Musixmatch API
JavaScript
211
star
86

svg-css-generator-examples

Tiny projects using generated code from different CSS & SVG generators
HTML
204
star
87

ciblog

Simple blog built on Codeigniter
PHP
202
star
88

larticles_api

Laravel 5.5 API using resources
PHP
193
star
89

codegig

Simple job find app for coders
CSS
192
star
90

node_push_notifications

Example using Node.js and service workers to send and show push notifications
JavaScript
186
star
91

bs4starter

Starter pack for Bootstrap 4 Beta
JavaScript
183
star
92

mongochat

Simple chat app using Mongo and websockets
HTML
178
star
93

microposts_fullstack_vue

Full stack vue and express
JavaScript
174
star
94

support-desk

Support ticket app built with the MERN stack
JavaScript
173
star
95

nestjs_rest_api

Rest api built with Nest and MongoDB
TypeScript
172
star
96

flask_sqlalchemy_rest

Products REST API using Flask, SQL Alchemy & Marshmallow
Python
171
star
97

next-13-crash-course

JavaScript
170
star
98

pollster_django_crash

Polling app built with Django (Django Crash Course)
Python
169
star
99

face_recognition_examples

Examples for Python Face Recognition library
Python
166
star
100

huddle_styled_components

Landing page from styled components crash course
JavaScript
166
star