I am having trouble with the below code. This is a basic table which displays users and I am trying to implement some sort functionality however it is not working.
When running I can click the sort buttons and they will update the sortParameters state accordingly, however, the function which requests the data from the API (getUsersFromAPI) does not recognise this state change. When running this function is supposed to fetch the data and then use the reducer to sort according to the updated sortParameters, but it instead is returning the usersList as it is received from the API and the console.log(sortParameters) returns the defaultSortParameters. I am not sure why sortParameters isn’t updating in this function when a sort button is clicked?
Any help would be greatly appreciated.
Thanks,
Greg
useState,
useReducer,
useEffect,
useLayoutEffect,
useContext,
} from "react";
import { useUser } from "../../contexts/UserContext";
import { usersListReducer } from "../../reducers/usersListReducer";
import {
API_users_usersGetAllUsers,
API_users_DeleteUser,
} from "../../publicFunctions/usersAPI";
// reactstrap components
import {
Card,
CardHeader,
CardBody,
CardTitle,
Table,
Row,
Col,
ButtonGroup,
Button,
} from "reactstrap";
import NewUser from "../Users/NewUser";
import classNames from "classnames";
const defaultSortParameters = { sortType: "NAME", sortDirection: true };
const Users = () => {
//------------------------- STATE -------------------------
const currentUser = useUser();
const [showNewUser, setShowNewUser] = useState(false);
const [sortParameters, setSortParameters] = useState(defaultSortParameters);
const [usersList, usersDispatch] = useReducer(usersListReducer, []);
//-------------------- CLICK HANDLING ---------------------
const deleteUser = async (id, name) => {
//check if trying to delete self
if (currentUser.id === id) return alert("Cannot delete self");
//check for delete confirmation
if (
window.confirm("Are you sure you want to delete user " + name) === true
) {
//remove user from userList if OK status is returned
const result = await API_users_DeleteUser(id);
if (result.statusText === "OK") {
usersDispatch({
type: "DELETE_USER_BY_ID",
payload: id,
});
}
}
};
//sorting by column
const sortUsers = (sortType) => {
setSortParameters({
...sortParameters,
sortType: sortType,
sortDirection: !sortParameters.sortDirection,
});
usersDispatch({
type: "SORT",
payload: {
sortType: sortType,
sortDirection: sortParameters.sortDirection,
},
});
console.log(sortParameters);
};
//----------------------- MOUNTING ------------------------
//get users from API when component mounts
useEffect(() => {
//get initial data on mount
getUsersFromAPI();
//set interval to refresh data periodically
const interval = setInterval(() => {
getUsersFromAPI();
}, 5000);
return () => {
clearInterval(interval);
};
}, []);
//----------------------- UPDATING ------------------------
const newUser = () => {
setShowNewUser(!showNewUser);
};
//----------------------- FUNCTIONS -----------------------
const getUsersFromAPI = async () => {
let result = await API_users_usersGetAllUsers();
if (result === undefined) {
console.log("ERROR: Cannot get users in Users.js");
} else {
usersDispatch({
type: "GET_USERS_FROM_API",
payload: result,
});
usersDispatch({
type: "SORT",
payload: {
sortType: sortParameters.sortType,
sortDirection: sortParameters.sortDirection,
},
});
}
console.log(sortParameters);
};
//------------------------ RENDER -------------------------
return (
<>
<div className="content">
<button onClick={() => console.log(currentUser)}>user</button>
<button onClick={() => console.log(sortParameters)}>sort params</button>
<Row>
<Col md="12">
<Card>
<Col sm="6">
<ButtonGroup
className="btn-group-toggle float-left"
data-toggle="buttons"
>
<Button
className={classNames("btn-simple", {
active: showNewUser === true,
})}
color="info"
id="0"
size="sm"
onClick={newUser}
>
New user
</Button>
</ButtonGroup>
</Col>
<Col>
{showNewUser ? (
<NewUser
setShowNewUser={setShowNewUser}
getUsersFromAPI={getUsersFromAPI}
/>
) : (
<></>
)}
<h2>Need a search Bar</h2>
</Col>
<CardHeader>
<CardTitle tag="h4">Users</CardTitle>
</CardHeader>
<CardBody>
<Table className="tablesorter" responsive>
<thead className="text-primary">
<tr>
<th>
Name{" "}
<button onClick={() => sortUsers("NAME")}>sort</button>
</th>
<th>
Email
<button onClick={() => sortUsers("EMAIL")}>sort</button>
</th>
<th>
Description
<button onClick={() => sortUsers("DESCRIPTION")}>
sort
</button>
</th>
<th>
Online
<button onClick={() => sortUsers("ONLINE")}>
sort
</button>
</th>
<input type="text" />
</tr>
</thead>
<tbody>
{usersList?.map((user) => {
return (
<tr>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.description}</td>
{user.is_online === false ? (
<td> false </td>
) : (
<>
{" "}
<td>true</td>{" "}
</>
)}
<td>
<Button
className={classNames("btn-simple")}
color="info"
id="deleteUser"
size="sm"
onClick={() => deleteUser(user.id, user.name)}
>
Delete
</Button>
</td>
</tr>
);
})}
</tbody>
</Table>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
};
export default Users;
reducer function sort code:
case "SORT":
//Switch by sort type
switch (action.payload.sortType) {
case "NAME":
if (action.payload.sortDirection === true) {
sortedUsersList.sort((a, b) => (a.name > b.name ? 1 : -1));
return sortedUsersList;
} else {
sortedUsersList.sort((a, b) => (a.name < b.name ? 1 : -1));
return sortedUsersList;
}
case "EMAIL":
if (action.payload.sortDirection === true) {
sortedUsersList.sort((a, b) => (a.email > b.email ? 1 : -1));
return sortedUsersList;
} else {
sortedUsersList.sort((a, b) => (a.email < b.email ? 1 : -1));
return sortedUsersList;
}
case "DESCRIPTION":
if (action.payload.sortDirection === true) {
sortedUsersList.sort((a, b) =>
a.description > b.description ? 1 : -1
);
return sortedUsersList;
} else {
sortedUsersList.sort((a, b) =>
a.description < b.description ? 1 : -1
);
return sortedUsersList;
}
case "ONLINE":
if (action.payload.sortDirection === true) {
sortedUsersList.sort((a, b) =>
a.is_online > b.is_online ? 1 : -1
);
return sortedUsersList;
} else {
sortedUsersList.sort((a, b) =>
a.is_online < b.is_online ? 1 : -1
);
return sortedUsersList;
}
}