An open API service indexing awesome lists of open source software.

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

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. Quiz

axios 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}


{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}


{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 (


Home Page



About




);
};
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}

{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;
```