Skip to content

Commit

Permalink
perf: ⚡ improves authors filtering
Browse files Browse the repository at this point in the history
Starts using react useMemo, so It only calculates the filteredAuthors if either the filter or the fetched data changes. Also, it is now filtering before mapping which also improves the performance
  • Loading branch information
gabrielborgesdm committed Aug 11, 2024
1 parent df2065c commit 8d408da
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 43 deletions.
28 changes: 6 additions & 22 deletions frontend/src/components/Hooks/UseFilterHook.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,17 @@
import { ChangeEvent, useState } from "react";
import { useState } from "react";

export const useFilterHook = () => {
const [filter, setFilter] = useState<string | null>(null);

const handleChangeFilter = (e: ChangeEvent<HTMLInputElement>): void => {
setFilter(e.target.value);
};

const shouldFilterInWith = (...properties: (unknown | undefined)[]): boolean => {
const isFilterFoundInProperties = (...properties: (unknown | undefined)[]): boolean => {
if (!filter) return true;

let anyPropertyMatch = false;

for (const property of properties) {
if (typeof property === "undefined") {
continue;
}

if (String(property).toLowerCase().includes(filter.toLowerCase())) {
anyPropertyMatch = true;
break;
}
}

return anyPropertyMatch;
return properties.some((property) => property && String(property).toLowerCase().includes(filter.toLowerCase()));
};

return {
handleChangeFilter,
shouldFilterInWith,
filter,
setFilter,
isFilterFoundInProperties,
};
};
43 changes: 25 additions & 18 deletions frontend/src/pages/Authors/Authors.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useMemo } from "react";
import ManagementService from "services/managementService";
import { useFilterHook } from "components/Hooks/UseFilterHook";
import { Author } from "types/author";
Expand All @@ -7,8 +7,16 @@ import useSWR from "swr";
const managementService = new ManagementService();

const Authors: React.FC = () => {
const { handleChangeFilter, shouldFilterInWith } = useFilterHook();
const { data: authorsData, error, isLoading } = useSWR("authors", () => managementService.getAuthors());
const { filter, setFilter, isFilterFoundInProperties } = useFilterHook();
const { data: authorsData, isLoading } = useSWR("authors", () => managementService.getAuthors());

const filteredAuthors = useMemo(() => {
if (!filter) return authorsData;

return authorsData?.filter(({ name, nationality, birthDate, email, id }: Author) =>
isFilterFoundInProperties(name, nationality, birthDate, email, id),
);
}, [authorsData, filter]);

return (
<>
Expand Down Expand Up @@ -37,7 +45,7 @@ const Authors: React.FC = () => {
<input
type="text"
id="table-search"
onChange={handleChangeFilter}
onChange={(e) => setFilter(e.target.value)}
className="block py-3 ps-10 text-sm border rounded-lg w-80 focus:ring-blue-500 focus:border-blue-500 "
placeholder="Search for items"
/>
Expand All @@ -51,7 +59,7 @@ const Authors: React.FC = () => {
</div>
<hr />
<div className="block max-h-[78dvh] overflow-y-auto">
{authorsData && authorsData.length > 0 ? (
{filteredAuthors && filteredAuthors.length > 0 ? (
<table className="w-full text-sm text-left rtl:text-right text-gray-500">
<thead className="text-xs uppercase ">
<tr>
Expand All @@ -70,19 +78,18 @@ const Authors: React.FC = () => {
</tr>
</thead>
<tbody>
{authorsData.map(
({ name, nationality, birthDate, email, id }: Author) =>
shouldFilterInWith(name, nationality, birthDate, email, id) && (
<tr key={id} className="border-b hover:bg-gray-50">
<th scope="row" className="px-1 py-4 font-medium text-gray-900 whitespace-nowrap">
{name}
</th>
<td className="px-1 py-4">{nationality}</td>
<td className="px-1 py-4">{birthDate}</td>
<td className="px-1 py-4">{email}</td>
</tr>
),
)}
{filteredAuthors.map(({ id, name, nationality, birthDate, email }) => (
<>
<tr key={id} className="border-b hover:bg-gray-50">
<th scope="row" className="px-1 py-4 font-medium text-gray-900 whitespace-nowrap">
{name}
</th>
<td className="px-1 py-4">{nationality}</td>
<td className="px-1 py-4">{birthDate}</td>
<td className="px-1 py-4">{email}</td>
</tr>
</>
))}
</tbody>
</table>
) : isLoading ? (
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/Books/Books.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const managementService = new ManagementService();

const Books: React.FC = () => {
const [books, setBooks] = useState<Book[]>([]);
const { handleChangeFilter, shouldFilterInWith } = useFilterHook();
const { setFilter, isFilterFoundInProperties } = useFilterHook();

useEffect(() => {
loadBooks();
Expand Down Expand Up @@ -49,7 +49,7 @@ const Books: React.FC = () => {
<input
type="text"
id="table-search"
onChange={handleChangeFilter}
onChange={(e) => setFilter(e.target.value)}
className="block py-3 ps-10 text-sm border rounded-lg w-80 focus:ring-blue-500 focus:border-blue-500 "
placeholder="Search for items"
/>
Expand Down Expand Up @@ -81,7 +81,7 @@ const Books: React.FC = () => {
{books?.length > 0 &&
books.map(
({ id, title, pages, authorsNames }: Book) =>
shouldFilterInWith(title, pages, id, authorsNames) && (
isFilterFoundInProperties(title, pages, id, authorsNames) && (
<tr key={id} className="border-b hover:bg-gray-50">
<th scope="row" className="px-1 py-4 font-medium text-gray-900 whitespace-nowrap">
{title}
Expand Down

0 comments on commit 8d408da

Please sign in to comment.