I would like advice on how to improve the overall speed and prevent lagging input, you will notice the input box lags especially when pressing backspace:
Assume the api at jsonplaceholder can change, so I dont want to use any named properties and keep it dynamic as possible.
I thought of extracting components or using memoization hooks but I wasnt sure… It is perhaps using too much DFS and BFS maybe there is a way to restructure the data so Im not doing this every time.
I also plan to turn the text into editable input fields
relevant files:
//entries
import useFetchPromiseAll from "../hooks/useFetchPromiseAll";
import { useState } from "react";
function highlight(value, highlight) {
const parts = value.toString().split(new RegExp(`(${highlight})`, "gi"));
return parts.map((part, index) => (
<span key={index}>
{part === highlight ? (
<b style={{ backgroundColor: "#ADD8E6" }}>{part}</b>
) : (
part
)}
</span>
));
}
function Entry({ entry, level, input }) {
return (
<div>
{Object.values(entry).map((x) => {
if (typeof x !== "object") {
return (
<div style={{ marginLeft: `${level * 10}px` }}>
{highlight(x, input)}
</div>
);
}
return (
<Entry level={level + 1} entry={Object.values(x)} input={input} />
);
})}
</div>
);
}
const params = ["users", "posts"];
function Entries() {
const { users, posts } = useFetchPromiseAll(params);
const entries = users?.map((user) => {
user[params[1]] = posts.filter((post) => post.userId === user.id);
return user;
});
const [input, setInput] = useState("");
const searchEntry = (entry) => {
const queue = [...Object.values(entry)];
while (queue.length > 0) {
const element = queue.shift();
if (typeof element === "object") {
queue.push(...Object.values(element));
} else {
if (element.toString().toLowerCase().includes(input.toLowerCase())) {
return true;
}
}
}
};
const filtered = entries?.filter((entry) => {
return searchEntry(entry);
});
return (
<>
{entries && (
<input value={input} onChange={(e) => setInput(e.target.value)} />
)}
{filtered?.map((entry) => (
<Entry key={entry.id} entry={entry} level={0} input={input} />
))}
</>
);
}
export default Entries;
//useFetchPromiseAll
import { useEffect, useState } from "react";
import getFetchData from "../utils/getFetchData";
function useFetchPromiseAll(params) {
const [data, setData] = useState([]);
useEffect(() => {
const Data = getFetchData(params);
Promise.all([...Data]).then((res) => {
const response = {};
for (let i = 0; i < res.length; i++) {
response[params[i]] = res[i];
}
setData(response);
});
}, [params]);
return data;
}
export default useFetchPromiseAll;
//GetFetchData utility
import { useEffect, useState } from "react";
import getFetchData from "../utils/getFetchData";
function useFetchPromiseAll(params) {
const [data, setData] = useState([]);
useEffect(() => {
const Data = getFetchData(params);
Promise.all([...Data]).then((res) => {
const response = {};
for (let i = 0; i < res.length; i++) {
response[params[i]] = res[i];
}
setData(response);
});
}, [params]);
return data;
}
export default useFetchPromiseAll;
Edit: Ive given some self thought, here is my analysis:
- if I do some of the work to reorganize the structuring of the data in the custom effect (outside of the main component) it will help (like maybe flattening the data?) . running Entry() (the DFS) on each render is too expensive, (the way that function is currently built… )
- if I fix the keys complaint and also possibl use a debouncing technique on input change It will fix the lagging.
- I also was wondering if this is a use case for the memo hooks of react or if those will really do much for me at all…
- in any case I still need to do the Breadth first search on input change its unavoidable as im searching for every occuarance.
- I didnt really want to do any processing work inside of that custom hook so I think an HOC is appropriate in this case?
Let me know your thoughts and if there is somethign I missed.