https://github.com/tabotcharlesbessong/all-react-from-john-smilga
This repository includes all what i have learned from John Smilga related to react he is one if not the best teacher on youtube and all over the internet
https://github.com/tabotcharlesbessong/all-react-from-john-smilga
ax raectjs react redux
Last synced: 7 months ago
JSON representation
This repository includes all what i have learned from John Smilga related to react he is one if not the best teacher on youtube and all over the internet
- Host: GitHub
- URL: https://github.com/tabotcharlesbessong/all-react-from-john-smilga
- Owner: TabotCharlesBessong
- Created: 2021-12-19T03:48:14.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2023-02-09T10:36:56.000Z (over 2 years ago)
- Last Synced: 2023-03-05T11:07:20.341Z (over 2 years ago)
- Topics: ax, raectjs, react, redux
- Language: JavaScript
- Homepage:
- Size: 17.4 MB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
#### All Projects
[Projects Site](https://react-projects.netlify.app/)
## Corresponding Tutorial Topics
#### useState
1. Birthday Reminder
#### useEffect and Conditional Rendering
2. Tours
3. Reviews
4. Questions
5. Menu
6. Tabs
7. Slider#### Forms
8. Lorem Ipsum Generator
9. Color Shades Generator
10. Grocery Bud#### useRef
11. Navbar
#### useContext
12. Modal And Sidebar
13. Stripe Submenus#### useReducer and useContext
14. Cart
#### React Router and useCallback
15. Cocktails
## Advanced Projects (Course Exclusive)
[Course Link](https://www.udemy.com/course/react-tutorial-and-projects-course/?couponCode=REACT-OCT)
16. Markdown Preview
17. Random Person
18. Pagination
19. Stock Photos
20. Dark Mode
21. Movie DB
22. Hacker News
23. Quizaxios tutorial section
# Axios Tutorial
#### React Course
[My React Course](https://www.udemy.com/course/react-tutorial-and-projects-course/?referralCode=FEE6A921AF07E2563CEF)
#### Docs
[Axios Docs](https://axios-http.com/docs/intro)
#### Install
```sh
npm install axios
``````js
```
#### First Request
- import axios
- axios.get(url)
- axios.post(url)
- axios.patch/put(url)
- axios.delete(ulr)- default get axios(url)
- returns a promise
- response data located in data property
- error in error.response```js
import axios from 'axios';const fetchData = async () => {
try {
// axios.get(), axios.post(),axios.put(), axios.delete()
const response = await axios(url);console.log(response);
} catch (error) {
console.log(error.response);
}
};
```#### Headers
- second argument
- axios.get(url,{})- third argument in requests with data
- axios.post(url,{data},{})```js
const fetchDadJoke = async () => {
try {
const { data } = await axios(url, {
headers: {
Accept: 'application/json',
},
});
// console.log(data);
setJoke(data.joke);
} catch (error) {
console.log(error.response);
}
};
```#### Post Request
- send data to the server
- axios.post(url, { data })
- more options (auth header) - axios.post(url, { data },{})```js
try {
const resp = await axios.post(url, { data });
} catch (error) {
console.log(error.response.data);
}
```#### Global Defaults
```js
axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded';
```#### Custom Instance
```js
const authFetch = axios.create({
baseURL: 'https://course-api.com',
headers: {
Accept: 'application/json',
},
});
```#### Interceptors
- global and custom
```js
authFetch.interceptors.request.use(
(request) => {
request.headers.common['Accept'] = `application/json`;
console.log('request sent');
// must return request
return request;
},
(error) => {
return Promise.reject(error);
}
);authFetch.interceptors.response.use(
(response) => {
console.log('got response');
return response;
},
(error) => {
console.log(error.response);
if (error.response.status === 404) {
// do something
console.log('NOT FOUND');
}
return Promise.reject(error);
}
);
```# Redux Toolkit
#### React Course
[My React Course](https://www.udemy.com/course/react-tutorial-and-projects-course/?referralCode=FEE6A921AF07E2563CEF)
#### Support
Find the App Useful? [You can always buy me a coffee](https://www.buymeacoffee.com/johnsmilga)
#### Docs
[Redux Toolkit Docs](https://redux-toolkit.js.org/introduction/getting-started)
#### Install Template
```sh
npx create-react-app my-app --template redux
```- @latest
```sh
npx create-react-app@latest my-app --template redux
```#### Existing App
```sh
npm install @reduxjs/toolkit react-redux
```#### @reduxjs/toolkit
consists of few libraries
- redux (core library, state management)
- immer (allows to mutate state)
- redux-thunk (handles async actions)
- reselect (simplifies reducer functions)#### Extras
- redux devtools
- combine reducers#### react-redux
connects our app to redux
#### Setup Store
- create store.js
```js
import { configureStore } from '@reduxjs/toolkit';export const store = configureStore({
reducer: {},
});
```#### Setup Provider
- index.js
```js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
// import store and provider
import { store } from './store';
import { Provider } from 'react-redux';ReactDOM.render(
,
document.getElementById('root')
);
```#### Setup Cart Slice
- application feature
- create features folder/cart
- create cartSlice.js```js
import { createSlice } from '@reduxjs/toolkit';const initialState = {
cartItems: [],
amount: 0,
total: 0,
isLoading: true,
};const cartSlice = createSlice({
name: 'cart',
initialState,
});console.log(cartSlice);
export default cartSlice.reducer;
```- store.js
```js
import { configureStore } from '@reduxjs/toolkit';
import cartReducer from './features/cart/cartSlice';export const store = configureStore({
reducer: {
cart: cartReducer,
},
});
```#### Redux DevTools
- extension
#### Access store value
- create components/Navbar.js
```js
import { CartIcon } from '../icons';
import { useSelector } from 'react-redux';const Navbar = () => {
const { amount } = useSelector((state) => state.cart);return (
redux toolkit
{amount}
);
};
export default Navbar;
```#### Hero Icons
- [Hero Icons](https://heroicons.com/)
```css
nav svg {
width: 40px;
color: var(--clr-white);
}
```#### Setup Cart
- cartSlice.js
```js
import cartItems from '../../cartItems';const initialState = {
cartItems: cartItems,
amount: 0,
total: 0,
isLoading: true,
};
```- create CartContainer.js and CartItem.js
- CartContainer.js```js
import React from 'react';
import CartItem from './CartItem';
import { useSelector } from 'react-redux';const CartContainer = () => {
const { cartItems, total, amount } = useSelector((state) => state.cart);if (amount < 1) {
return (
{/* cart header */}
your bag
is currently empty
);
}
return (
{/* cart header */}
your bag
{/* cart items */}
{cartItems.map((item) => {
return ;
})}
{/* cart footer */}
total ${total}
clear cart
);
};export default CartContainer;
```- CartItems.js
```js
import React from 'react';
import { ChevronDown, ChevronUp } from '../icons';const CartItem = ({ id, img, title, price, amount }) => {
return (
![]()
{title}
${price}
{/* remove button */}
remove
{/* increase amount */}
{/* amount */}
{amount}
{/* decrease amount */}
);
};export default CartItem;
```#### First Reducer
- cartSlice.js
- Immer library```js
const cartSlice = createSlice({
name: 'cart',
initialState,
reducers: {
clearCart: (state) => {
state.cartItems = [];
},
},
});export const { clearCart } = cartSlice.actions;
```- create action
```js
const ACTION_TYPE = 'ACTION_TYPE';const actionCreator = (payload) => {
return { type: ACTION_TYPE, payload: payload };
};
```- CartContainer.js
```js
import React from 'react';
import CartItem from './CartItem';
import { useDispatch, useSelector } from 'react-redux';const CartContainer = () => {
const dispatch = useDispatch();return (
{
dispatch(clearCart());
}}
>
clear cart
);
};export default CartContainer;
```#### Remove, Increase, Decrease
- cartSlice.js
```js
import { createSlice } from '@reduxjs/toolkit';
import cartItems from '../../cartItems';const initialState = {
cartItems: [],
amount: 0,
total: 0,
isLoading: true,
};const cartSlice = createSlice({
name: 'cart',
initialState,
reducers: {
clearCart: (state) => {
state.cartItems = [];
},
removeItem: (state, action) => {
const itemId = action.payload;
state.cartItems = state.cartItems.filter((item) => item.id !== itemId);
},
increase: (state, { payload }) => {
const cartItem = state.cartItems.find((item) => item.id === payload.id);
cartItem.amount = cartItem.amount + 1;
},
decrease: (state, { payload }) => {
const cartItem = state.cartItems.find((item) => item.id === payload.id);
cartItem.amount = cartItem.amount - 1;
},
calculateTotals: (state) => {
let amount = 0;
let total = 0;
state.cartItems.forEach((item) => {
amount += item.amount;
total += item.amount * item.price;
});
state.amount = amount;
state.total = total;
},
},
});export const { clearCart, removeItem, increase, decrease, calculateTotals } =
cartSlice.actions;export default cartSlice.reducer;
```- CartItem.js
```js
import React from 'react';
import { ChevronDown, ChevronUp } from '../icons';import { useDispatch } from 'react-redux';
import { removeItem, increase, decrease } from '../features/cart/cartSlice';const CartItem = ({ id, img, title, price, amount }) => {
const dispatch = useDispatch();return (
![]()
{title}
${price}
{/* remove button */}
{
dispatch(removeItem(id));
}}
>
remove
{/* increase amount */}
{
dispatch(increase({ id }));
}}
>
{/* amount */}
{amount}
{/* decrease amount */}
{
if (amount === 1) {
dispatch(removeItem(id));
return;
}
dispatch(decrease({ id }));
}}
>
);
};export default CartItem;
```- App.js
```js
import { useEffect } from 'react';
import Navbar from './components/Navbar';
import CartContainer from './components/CartContainer';
import { useSelector, useDispatch } from 'react-redux';
import { calculateTotals } from './features/cart/cartSlice';function App() {
const { cartItems } = useSelector((state) => state.cart);
const dispatch = useDispatch();
useEffect(() => {
dispatch(calculateTotals());
}, [cartItems]);return (
);
}export default App;
```#### Modal
- create components/Modal.js
```js
const Modal = () => {
return (
Remove all items from your shopping cart?
confirm
cancel
);
};
export default Modal;
```- App.js
```js
return (
);
```#### modal slice
- create features/modal/modalSlice.js
```js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
isOpen: false,
};const modalSlice = createSlice({
name: 'modal',
initialState,
reducers: {
openModal: (state, action) => {
state.isOpen = true;
},
closeModal: (state, action) => {
state.isOpen = false;
},
},
});export const { openModal, closeModal } = modalSlice.actions;
export default modalSlice.reducer;
```- App.js
```js
const { isOpen } = useSelector((state) => state.modal);return (
{isOpen && }
);
```#### toggle modal
- CartContainer.js
```js
import { openModal } from '../features/modal/modalSlice';return (
{
dispatch(openModal());
}}
>
clear cart
);
```- Modal.js
```js
import { closeModal } from '../features/modal/modalSlice';
import { useDispatch } from 'react-redux';
import { clearCart } from '../features/cart/cartSlice';const Modal = () => {
const dispatch = useDispatch();return (
Remove all items from your shopping cart?
{
dispatch(clearCart());
dispatch(closeModal());
}}
>
confirm
{
dispatch(closeModal());
}}
>
cancel
);
};
export default Modal;
```#### async functionality with createAsyncThunk
- [Course API](https://course-api.com/)
- https://course-api.com/react-useReducer-cart-project
- cartSlice.js- action type
- callback function
- lifecycle actions```js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';const url = 'https://course-api.com/react-useReducer-cart-project';
export const getCartItems = createAsyncThunk('cart/getCartItems', () => {
return fetch(url)
.then((resp) => resp.json())
.catch((err) => console.log(error));
});const cartSlice = createSlice({
name: 'cart',
initialState,
extraReducers: {
[getCartItems.pending]: (state) => {
state.isLoading = true;
},
[getCartItems.fulfilled]: (state, action) => {
console.log(action);
state.isLoading = false;
state.cartItems = action.payload;
},
[getCartItems.rejected]: (state) => {
state.isLoading = false;
},
},
});
```- App.js
```js
import { calculateTotals, getCartItems } from './features/cart/cartSlice';function App() {
const { cartItems, isLoading } = useSelector((state) => state.cart);useEffect(() => {
dispatch(getCartItems());
}, []);if (isLoading) {
return (
Loading...
);
}return (
{isOpen && }
);
}export default App;
```#### Options
```sh
npm install axios
```- cartSlice.js
```js
export const getCartItems = createAsyncThunk(
'cart/getCartItems',
async (name, thunkAPI) => {
try {
// console.log(name);
// console.log(thunkAPI);
// console.log(thunkAPI.getState());
// thunkAPI.dispatch(openModal());
const resp = await axios(url);return resp.data;
} catch (error) {
return thunkAPI.rejectWithValue('something went wrong');
}
}
);
```# React Router 6
#### React Course
[My React Course](https://www.udemy.com/course/react-tutorial-and-projects-course/?referralCode=FEE6A921AF07E2563CEF)
#### Support
Find the App Useful? [You can always buy me a coffee](https://www.buymeacoffee.com/johnsmilga)
#### Run Complete Project
- index.js
```js
// import App from './App';
import App from './final/App';
```#### Docs
[React Router Docs](https://reactrouter.com/docs/en/v6/getting-started/overview)
#### Install
```sh
npm install react-router-dom@6
```#### First Pages
- App.js
```js
import { BrowserRouter, Routes, Route } from 'react-router-dom';function App() {
return (
home page} />
testing
}
/>
);
}export default App;
```#### Components
- App.js
```js
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Products from './pages/Products';function App() {
return (
} />
} />
} />
);
}export default App;
```#### Links
- Home.js, About.js
```js
import { Link } from 'react-router-dom';const Home = () => {
return (
);
};
export default Home;
```#### Error Page
- App.js
```js
function App() {
return (
} />
} />
} />
} />
);
}
```- Error.js
```js
import { Link } from 'react-router-dom';const Error = () => {
return (
404
page not found
back home
);
};
export default Error;
```#### Nested Pages
- will refactor few times
- App.js
```js
function App() {
return (
}>
} />
} />
} />
);
}
```#### Shared Layout
- Home.js
```js
import { Link, Outlet } from 'react-router-dom';const Home = () => {
return (
Home Page
);
};
export default Home;
```#### Navbar
- Navbar.js
```js
import { Link } from 'react-router-dom';const Navbar = () => {
return (
Home
About
Products
);
};
export default Navbar;
```- Home.js
```js
import { Link, Outlet } from 'react-router-dom';
import Navbar from '../components/Navbar';
const Home = () => {
return (
<>
>
);
};
export default Home;
```#### Index Routes
- Index routes render in the parent routes outlet at the parent route's path.
- Index routes match when a parent route matches but none of the other children match.
- Index routes are the default child route for a parent route.
- Index routes render when the user hasn't clicked one of the items in a navigation list yet.- copy Home.js content
- SharedLayout.js```js
import { Link, Outlet } from 'react-router-dom';
import Navbar from '../components/Navbar';
const SharedLayout = () => {
return (
<>
>
);
};
export default SharedLayout;
```- Home.js
```js
const Home = () => {
return (
Home Page
);
};
export default Home;
```- App.js
```js
function App() {
return (
}>
} />
} />
} />
} />
);
}
```#### NavLink (style)
- StyledNavbar.js
```js
import { NavLink } from 'react-router-dom';{
return { color: isActive ? 'red' : 'grey' };
}}
>
Home
;
```#### NavLink (className)
- StyledNavbar.js
```js
(isActive ? 'link active' : 'link')}
>
Home
```
#### Reading URL Params
- App.js
```js
function App() {
return (
}>
} />
} />
} />
} />
} />
);
}
```#### Single Product
- SingleProduct.js
```js
import { Link, useParams } from 'react-router-dom';
import products from '../data';
const SingleProduct = () => {
const { productId } = useParams();return (
{productId}
back to products
);
};export default SingleProduct;
```#### Products Page
- Products.js
```js
import { Link } from 'react-router-dom';
import products from '../data';
const Products = () => {
return (
products
{products.map((product) => {
return (
{product.name}
more info
);
})}
);
};export default Products;
```#### Single Product
- SingleProduct.js
```js
import { Link, useParams } from 'react-router-dom';
import products from '../data';
const SingleProduct = () => {
const { productId } = useParams();
const product = products.find((product) => product.id === productId);
const { image, name } = product;return (
![]()
{name}
back to products
);
};export default SingleProduct;
```#### useNavigate()
[ (?.) or Optional Chaining Explained](https://youtu.be/PuEGrylM1x8)
- App.js
```js
function App() {
const [user, setUser] = useState(null);return (
}>
} />
} />
} />
} />
} />
} />
} />
);
}
```- Login.js
```js
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
const Login = ({ setUser }) => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
if (!name || !email) return;
setUser({ name: name, email: email });
navigate('/dashboard');
};```
[ (?.) or Optional Chaining Explained](https://youtu.be/PuEGrylM1x8)
- Dashboard.js
```js
const Dashboard = ({ user }) => {
return (
Hello, {user?.name}
);
};
export default Dashboard;
```#### Protected Route
- App.js
```js
}
/>
```- ProtectedRoute.js
```js
import { Navigate } from 'react-router-dom';const ProtectedRoute = ({ children, user }) => {
if (!user) {
return ;
}
return children;
};export default ProtectedRoute;
```