├── 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 | user 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 | --------------------------------------------------------------------------------