Stack Overflow Asked on November 7, 2021
I’m new to React hooks and am attempting to make a custom hook that will concatenate arrays and remove the duplicate objects. I only want the hook to run that process if the prop changes to avoid un-needed processing.
I was attempting to cache concatenated results and use useMemo
to only run if that changes but that does not work. Obviously, I am missing something with the way useMemo
works.
I have tried various things mainly around slight tweaks, for example adding arrays to the useMemo
dependencies as opposed to merged. Any help would be great. Thanks.
import * as React from "react";
let merged: any = [];
let result: any = [];
export const useRemoveDuplicateObjects = (arrays: any, value: string) => {
merged = arrays.flat();
const key = (item: any) => {
return item[value];
};
const process = () => {
result = [...new Map(merged.map((item: any) => [key(item), item])).values()];
};
React.useMemo(() => {
if (merged.length) {
process();
}
}, [merged]);
return [result];
};
Few things are not done properly here.
For starters, when you pass an array as a second parameter to useMemo
, React will compare its values with strict equality, i.e. ===
. The comparison
will fail every time because you reassign your merged
variable
every time the hook is run.
If you want to compare the previous and new values contained by your array, there are 2 ways I can think of:
merged
as a second parameter instead of putting it
in an array, this way React would compare the values within it
directly. I don't know for sure if this would work, since maybe the
values won't always be in the same order.useState
hook for instance) and compare this old
value with the new one yourself, and then set a boolean
accordingly. This way, this boolean can be passed as a second
parameter within an array to your useMemo
.Also, as the documentation states, useMemo "returns an expensively computed value". So, to go along with how it works, you should get the "result" value this way :
const result = React.useMemo(() => {
if (merged.length) {
return [...new Map(merged.map((item: any) => [key(item), item])).values()]
}
return []
}, merged); // will or won't work, I'd say go with the comparison yourself as stated before
Finally, if you only want to return a single value from your hook, there's no need to wrap it in an array, you could just do it this way:
return result;
Answered by Littletime on November 7, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP