improvement: adopted infinity scroll in users and contacts

This commit is contained in:
canove
2020-09-03 17:43:04 -03:00
parent dfde175c07
commit 514f1c3b75
3 changed files with 75 additions and 44 deletions

View File

@@ -7,7 +7,7 @@ const User = require("../models/User");
const { getIO } = require("../libs/socket"); const { getIO } = require("../libs/socket");
exports.index = async (req, res) => { exports.index = async (req, res) => {
const { searchParam = "", pageNumber = 1, rowsPerPage = 10 } = req.query; const { searchParam = "", pageNumber = 1 } = req.query;
const whereCondition = { const whereCondition = {
[Op.or]: [ [Op.or]: [
@@ -22,7 +22,7 @@ exports.index = async (req, res) => {
], ],
}; };
let limit = +rowsPerPage; let limit = 20;
let offset = limit * (pageNumber - 1); let offset = limit * (pageNumber - 1);
const { count, rows: users } = await User.findAndCountAll({ const { count, rows: users } = await User.findAndCountAll({
@@ -33,7 +33,9 @@ exports.index = async (req, res) => {
order: [["createdAt", "DESC"]], order: [["createdAt", "DESC"]],
}); });
return res.status(200).json({ users, count }); const hasMore = count > offset + users.length;
return res.status(200).json({ users, count, hasMore });
}; };
exports.store = async (req, res, next) => { exports.store = async (req, res, next) => {

View File

@@ -47,25 +47,22 @@ const reducer = (state, action) => {
return [...state, ...newContacts]; return [...state, ...newContacts];
} }
if (action.type === "UPDATE_CONTACT") { if (action.type === "UPDATE_CONTACTS") {
const updatedContact = action.payload; const contact = action.payload;
const contactIndex = state.findIndex(c => c.id === updatedContact.id); const contactIndex = state.findIndex(c => c.id === contact.id);
if (contactIndex !== -1) { if (contactIndex !== -1) {
state[contactIndex] = updatedContact; state[contactIndex] = contact;
} }
return [...state]; return [contact, ...state];
} }
if (action.type === "DELETE_CONTACT") { if (action.type === "DELETE_CONTACT") {
const contactId = action.payload; const contactId = action.payload;
console.log("cai aqui", contactId);
const contactIndex = state.findIndex(c => c.id === contactId); const contactIndex = state.findIndex(c => c.id === contactId);
if (contactIndex !== -1) { if (contactIndex !== -1) {
console.log("cai no if");
state.splice(contactIndex, 1); state.splice(contactIndex, 1);
} }
return [...state]; return [...state];
@@ -119,7 +116,7 @@ const Contacts = () => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL); const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.on("contact", data => { socket.on("contact", data => {
if (data.action === "update" || data.action === "create") { if (data.action === "update" || data.action === "create") {
dispatch({ type: "UPDATE_CONTACT", payload: data.contact }); dispatch({ type: "UPDATE_CONTACTS", payload: data.contact });
} }
if (data.action === "delete") { if (data.action === "delete") {

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useReducer } from "react";
import openSocket from "socket.io-client"; import openSocket from "socket.io-client";
@@ -28,6 +28,45 @@ import TableRowSkeleton from "../../components/TableRowSkeleton";
import UserModal from "../../components/UserModal"; import UserModal from "../../components/UserModal";
import ConfirmationModal from "../../components/ConfirmationModal"; import ConfirmationModal from "../../components/ConfirmationModal";
const reducer = (state, action) => {
if (action.type === "LOAD_USERS") {
const users = action.payload;
const newUsers = [];
users.forEach(user => {
const userIndex = state.findIndex(u => u.id === user.id);
if (userIndex !== -1) {
state[userIndex] = user;
} else {
newUsers.push(user);
}
});
return [...state, ...newUsers];
}
if (action.type === "UPDATE_USERS") {
const user = action.payload;
const userIndex = state.findIndex(u => u.id === user.id);
if (userIndex !== -1) {
state[userIndex] = user;
}
return [user, ...state];
}
if (action.type === "DELETE_USER") {
const userId = action.payload;
const userIndex = state.findIndex(u => u.id === userId);
if (userIndex !== -1) {
state.splice(userIndex, 1);
}
return [...state];
}
};
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles(theme => ({
mainPaper: { mainPaper: {
flex: 1, flex: 1,
@@ -42,22 +81,24 @@ const Users = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [pageNumber, setPageNumber] = useState(1); const [pageNumber, setPageNumber] = useState(1);
const [hasMore, setHasMore] = useState(false);
const [selectedUserId, setSelectedUserId] = useState(null); const [selectedUserId, setSelectedUserId] = useState(null);
const [userModalOpen, setUserModalOpen] = useState(false); const [userModalOpen, setUserModalOpen] = useState(false);
const [confirmModalOpen, setConfirmModalOpen] = useState(false); const [confirmModalOpen, setConfirmModalOpen] = useState(false);
const [deletingUser, setDeletingUser] = useState(null); const [deletingUser, setDeletingUser] = useState(null);
const [searchParam, setSearchParam] = useState(""); const [searchParam, setSearchParam] = useState("");
const [users, setUsers] = useState([]); const [users, dispatch] = useReducer(reducer, []);
useEffect(() => { useEffect(() => {
setLoading(true); setLoading(true);
const delayDebounceFn = setTimeout(() => { const delayDebounceFn = setTimeout(() => {
const fetchUsers = async () => { const fetchUsers = async () => {
try { try {
const res = await api.get("/users/", { const { data } = await api.get("/users/", {
params: { searchParam, pageNumber }, params: { searchParam, pageNumber },
}); });
setUsers(res.data.users); dispatch({ type: "LOAD_USERS", payload: data.users });
setHasMore(data.hasMore);
setLoading(false); setLoading(false);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
@@ -73,11 +114,11 @@ const Users = () => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL); const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.on("user", data => { socket.on("user", data => {
if (data.action === "update" || data.action === "create") { if (data.action === "update" || data.action === "create") {
updateUsers(data.user); dispatch({ type: "UPDATE_USERS", payload: data.user });
} }
if (data.action === "delete") { if (data.action === "delete") {
deleteUser(data.userId); dispatch({ type: "DELETE_USER", payload: +data.userId });
} }
}); });
@@ -86,31 +127,6 @@ const Users = () => {
}; };
}, []); }, []);
const updateUsers = user => {
setUsers(prevState => {
const userIndex = prevState.findIndex(c => c.id === user.id);
if (userIndex === -1) {
return [user, ...prevState];
}
const aux = [...prevState];
aux[userIndex] = user;
return aux;
});
};
const deleteUser = userId => {
setUsers(prevState => {
const userIndex = prevState.findIndex(c => c.id === +userId);
if (userIndex === -1) return prevState;
const aux = [...prevState];
aux.splice(userIndex, 1);
return aux;
});
};
const handleOpenUserModal = () => { const handleOpenUserModal = () => {
setSelectedUserId(null); setSelectedUserId(null);
setUserModalOpen(true); setUserModalOpen(true);
@@ -141,6 +157,18 @@ const Users = () => {
setPageNumber(1); setPageNumber(1);
}; };
const loadMore = () => {
setPageNumber(prevState => prevState + 1);
};
const handleScroll = e => {
if (!hasMore || loading) return;
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
if (scrollHeight - (scrollTop + 100) < clientHeight) {
loadMore();
}
};
return ( return (
<MainContainer> <MainContainer>
<ConfirmationModal <ConfirmationModal
@@ -182,7 +210,11 @@ const Users = () => {
</Button> </Button>
</MainHeaderButtonsWrapper> </MainHeaderButtonsWrapper>
</MainHeader> </MainHeader>
<Paper className={classes.mainPaper} variant="outlined"> <Paper
className={classes.mainPaper}
variant="outlined"
onScroll={handleScroll}
>
<Table size="small"> <Table size="small">
<TableHead> <TableHead>
<TableRow> <TableRow>