├── README.md
├── .gitignore
├── src
├── index.css
├── index.js
└── App.js
├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── craco.config.js
├── tailwind.config.js
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | # React-InfiniteLoading
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ms-yogi/React-InfiniteLoading/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ms-yogi/React-InfiniteLoading/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ms-yogi/React-InfiniteLoading/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/craco.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | style: {
3 | postcss: {
4 | plugins: [require('tailwindcss'), require('autoprefixer')],
5 | },
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
3 | darkMode: false, // or 'media' or 'class'
4 | theme: {
5 | extend: {},
6 | },
7 | variants: {
8 | extend: {},
9 | },
10 | plugins: [],
11 | };
12 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 |
6 | ReactDOM.render(
7 |
8 |
9 | ,
10 | document.getElementById('root')
11 | );
12 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lazyload",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@craco/craco": "^6.2.0",
7 | "axios": "^0.21.1",
8 | "cra-template": "1.1.2",
9 | "react": "^17.0.2",
10 | "react-dom": "^17.0.2",
11 | "react-scripts": "4.0.3"
12 | },
13 | "scripts": {
14 | "start": "craco start",
15 | "build": "craco build",
16 | "test": "craco test",
17 | "eject": "react-scripts eject"
18 | },
19 | "eslintConfig": {
20 | "extends": [
21 | "react-app",
22 | "react-app/jest"
23 | ]
24 | },
25 | "browserslist": {
26 | "production": [
27 | ">0.2%",
28 | "not dead",
29 | "not op_mini all"
30 | ],
31 | "development": [
32 | "last 1 chrome version",
33 | "last 1 firefox version",
34 | "last 1 safari version"
35 | ]
36 | },
37 | "devDependencies": {
38 | "autoprefixer": "^9.8.6",
39 | "postcss": "^7.0.36",
40 | "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.7"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import { useEffect, useState, useRef } from 'react';
3 |
4 | const TOTAL_PAGES = 3;
5 |
6 | const App = () => {
7 | const [loading, setLoading] = useState(true);
8 | const [allUsers, setAllUsers] = useState([]);
9 | const [pageNum, setPageNum] = useState(1);
10 | const [lastElement, setLastElement] = useState(null);
11 |
12 | const observer = useRef(
13 | new IntersectionObserver((entries) => {
14 | const first = entries[0];
15 | if (first.isIntersecting) {
16 | setPageNum((no) => no + 1);
17 | }
18 | })
19 | );
20 |
21 | const callUser = async () => {
22 | setLoading(true);
23 | let response = await axios.get(
24 | `https://randomuser.me/api/?page=${pageNum}&results=25&seed=abc`
25 | );
26 | let all = new Set([...allUsers, ...response.data.results]);
27 | setAllUsers([...all]);
28 | setLoading(false);
29 | };
30 |
31 | useEffect(() => {
32 | if (pageNum <= TOTAL_PAGES) {
33 | callUser();
34 | }
35 | }, [pageNum]);
36 |
37 | useEffect(() => {
38 | const currentElement = lastElement;
39 | const currentObserver = observer.current;
40 |
41 | if (currentElement) {
42 | currentObserver.observe(currentElement);
43 | }
44 |
45 | return () => {
46 | if (currentElement) {
47 | currentObserver.unobserve(currentElement);
48 | }
49 | };
50 | }, [lastElement]);
51 |
52 | const UserCard = ({ data }) => {
53 | return (
54 |
55 |
56 |

61 |
62 |
63 |
64 |
65 | {data.name.first} {data.name.last}
66 |
67 |
68 | {data.location.city}, {data.location.country}
69 |
70 |
71 | {data.email}
72 |
73 |
74 |
75 | );
76 | };
77 |
78 | return (
79 |
80 |
All users
81 |
82 |
83 | {allUsers.length > 0 &&
84 | allUsers.map((user, i) => {
85 | return i === allUsers.length - 1 &&
86 | !loading &&
87 | pageNum <= TOTAL_PAGES ? (
88 |
92 |
93 |
94 | ) : (
95 |
99 | );
100 | })}
101 |
102 | {loading &&
loading...
}
103 |
104 | {pageNum - 1 === TOTAL_PAGES && (
105 |
♥
106 | )}
107 |
108 | );
109 | };
110 |
111 | export default App;
112 |
--------------------------------------------------------------------------------