Skip to content

Commit

Permalink
fix: prevent table from rerendering when opening modals (#15375)
Browse files Browse the repository at this point in the history
> Addresses #14851 

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

<!-- Note that API documentation changes are now addressed by the
product design team. -->

- [x] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Jacob Shandling <[email protected]>
jahzielv and Jacob Shandling authored Nov 30, 2023
1 parent e413da2 commit 837602a
Showing 2 changed files with 69 additions and 51 deletions.
2 changes: 2 additions & 0 deletions changes/14851-table-reload
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fixes a bug where opening a modal on the Users page would cause the table to reset to the first
page of users.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useCallback, useContext } from "react";
import React, { useState, useCallback, useContext, useMemo } from "react";
import { InjectedRouter } from "react-router";
import { useQuery } from "react-query";
import memoize from "memoize-one";
@@ -141,32 +141,18 @@ const UsersTable = ({ router }: IUsersTableProps): JSX.Element => {

// FUNCTIONS

const combineUsersAndInvites = memoize(
const combineUsersAndInvites = useCallback(
(usersData, invitesData, currentUserId) => {
return combineDataSets(usersData, invitesData, currentUserId);
}
},
[]
);

const goToUserSettingsPage = () => {
const { USER_SETTINGS } = paths;
router.push(USER_SETTINGS);
};

// NOTE: this is called once on the initial rendering. The initial render of
// the TableContainer child component calls this handler.
const onTableQueryChange = (queryData: ITableQueryData) => {
const { searchQuery, sortHeader, sortDirection } = queryData;
let sortBy: any = []; // TODO
if (sortHeader !== "") {
sortBy = [{ id: sortHeader, direction: sortDirection }];
}

setQuerySearchText(searchQuery);

refetchUsers();
refetchInvites();
};

const onActionSelect = (value: string, user: IUser | IInvite) => {
switch (value) {
case "edit":
@@ -514,44 +500,74 @@ const UsersTable = ({ router }: IUsersTableProps): JSX.Element => {
const tableDataError =
loadingUsersError || loadingInvitesError || loadingTeamsError;

let tableData: unknown = [];
if (!loadingTableData && !tableDataError) {
tableData = combineUsersAndInvites(users, invites, currentUser?.id);
}
const tableData = useMemo(
() =>
!loadingTableData && !tableDataError
? combineUsersAndInvites(users, invites, currentUser?.id)
: [],
[
loadingTableData,
tableDataError,
users,
invites,
currentUser?.id,
combineUsersAndInvites,
]
);

const renderTable = useCallback(() => {
// NOTE: this is called once on the initial rendering. The initial render of
// the TableContainer child component calls this handler.
const onTableQueryChange = (queryData: ITableQueryData) => {
const { searchQuery } = queryData;

const emptyState = {
header: "No users match the current criteria.",
info:
"Expecting to see users? Try again in a few seconds as the system catches up.",
};
setQuerySearchText(searchQuery);

refetchUsers();
refetchInvites();
};

const emptyState = {
header: "No users match the current criteria.",
info:
"Expecting to see users? Try again in a few seconds as the system catches up.",
};

return (
<TableContainer
columns={tableHeaders}
data={tableData}
isLoading={loadingTableData}
defaultSortHeader={"name"}
defaultSortDirection={"asc"}
inputPlaceHolder={"Search by name or email"}
actionButton={{
name: "create user",
buttonText: "Create user",
onActionButtonClick: toggleCreateUserModal,
}}
onQueryChange={onTableQueryChange}
resultsTitle={"users"}
emptyComponent={() => EmptyTable(emptyState)}
searchable
showMarkAllPages={false}
isAllPagesSelected={false}
isClientSidePagination
/>
);
}, [
tableHeaders,
tableData,
loadingTableData,
toggleCreateUserModal,
refetchUsers,
refetchInvites,
]);

return (
<>
{/* TODO: find a way to move these controls into the table component */}
{tableDataError ? (
<TableDataError />
) : (
<TableContainer
columns={tableHeaders}
data={tableData}
isLoading={loadingTableData}
defaultSortHeader={"name"}
defaultSortDirection={"asc"}
inputPlaceHolder={"Search by name or email"}
actionButton={{
name: "create user",
buttonText: "Create user",
onActionButtonClick: toggleCreateUserModal,
}}
onQueryChange={onTableQueryChange}
resultsTitle={"users"}
emptyComponent={() => EmptyTable(emptyState)}
searchable
showMarkAllPages={false}
isAllPagesSelected={false}
isClientSidePagination
/>
)}
{tableDataError ? <TableDataError /> : renderTable()}
{showCreateUserModal && renderCreateUserModal()}
{showEditUserModal && renderEditUserModal()}
{showDeleteUserModal && renderDeleteUserModal()}

0 comments on commit 837602a

Please sign in to comment.