Seeing some weird things within the component that I am currently working on. So, I am having a server side paginated table, On every API call I am pushing the new records to the existing array. I am using fetchBaseQuery to make an API call.
Code to achieve it
let response = useGetQuery(request); // This hook will perform the API call
const records =
response.data?.records;
React.useEffect(() => {
if (records) {
setTableRecords((prevState: any) => [
...prevState,
...records,
]);
}
}, [records]);
Test case for this
jest.mock("../endpoints", () => ({
...jest.requireActual("../endpoints"),
useGetQuery: () => ({
isSuccess: true,
data: {
message: "Success",
records: [], // It gets into infinte loop if I provide this key while mocking
},
}),
}));
test("should mount", () => {
const component = renderer.create(<SomeComponent/>);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
As, per my understanding if we use array as a dependency in the useEffect
hook, it might lead to an infinite loop as React uses shallow comparison to check if the dependency’s reference has changed. To fix this, I tried using useRef
hook, but that doesn't work as per my use case as useRef doesn’t notify you when its content changes.
I then tried by making the response.data
object as a dependency to the useEffect hook, but as per the shallow comparison it is also leading to the infinite loop, so I was then trying to fix it with useMemo
hook but got no luck as if I pass the dependency as the object it was again leading to the same problem & passing no dependency doesn't work for me.
Is there any other way that I can handle this situation better?
CodePudding user response:
I use the useEffect hook, but instead of passing the api response as an array, I use some parameter, for example if I call an api to get images based on a category, I will only call the api when the category changes:
const [state, setState] = useState({
loading: true,
data: [],
});
useEffect(() => {
myApiMethod(category).then((gifs) => {
setState({
loading: false,
data: gifs,
});
});
}, [category]);
CodePudding user response:
Stringify the Array that you are passing in the dependency array if the array is not too large.
let response = useGetQuery(request); // This hook will perform the API call
const records =
response.data?.records;
React.useEffect(() => {
if (records) {
setTableRecords((prevState: any) => [
...prevState,
...records,
]);
}
}, [JSON.stringify(records)]);