useInfiniteQuery throws Cannot read properties of undefined (reading 'length') #7455
-
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 10 replies
-
Don't know the cause, but changing queryKey solved the problem |
Beta Was this translation helpful? Give feedback.
-
After upgrading from version 4 to version 5, we also began encountering this issue. We checked our query key, which is used only once in the useInfiniteQuery method, but it is used more than once during manual cache updates using the setQueryData method. |
Beta Was this translation helpful? Give feedback.
-
i have alsomist the same issue right now as wel i hope i can et a solution this is my rsc warpping the cclient component import { fetchAllProducts } from "@/actions"; // Define the expected parameter types export default async function Page({
} and this is my client comonent "use client"; import { fetchAllProducts, IProduct } from "@/actions"; const PRODUCTS_PER_PAGE = 12; interface ProductGridProps { interface ProductsPage { export default function GridContainer({ order }: ProductGridProps) {
} and this is the function ttself thats being called export async function fetchAllProducts(
} everything works fine , i get the necessary data , except that i keep getting this eroor , i have treid to handle all undeifned properties and null checks , but still the same issue, i hoe i can get some help |
Beta Was this translation helpful? Give feedback.
-
v5.83.0 I have two places where I call fetchNextPage, the call from search button crashes with the error above in comments. But when I call it from another button it fetchs data without error, unique queryKey been used export default function SearchModal<T>({
title,
subTitle,
searchFunction,
setSearchResult,
initialData,
searchFields,
offlineSearch = false,
children,
isOpen,
onClose,
}: SearchModalProps<T>) {
const [searchText, setSearchText] = useState('');
const queryKey = [`search-${title}`, searchText];
const { data, isLoading, status, fetchNextPage, refetch } = useInfiniteQuery({
queryKey,
queryFn: async ({ pageParam }) => {
if (!searchText) return { nextPageParam: null, data: initialData ?? [] };
return await searchFunction(searchText, pageParam);
},
getNextPageParam: (lastPage) => lastPage.nextPageParam,
initialPageParam: null,
enabled: false,
});
const items = useMemo(() => data?.pages?.flatMap((page) => page.data) ?? [], [data]);
const filterResult = () => {
const sanitizedText = sanitizeString(searchText).toLowerCase();
if (initialData) {
const result = initialData.filter(
(item) =>
searchFields.some((field) => {
return (
item[field.key] &&
sanitizeString(String(item[field.key]))
.toLowerCase()
.includes(sanitizedText)
);
}) || !searchText,
);
return result;
}
};
const onSearch = async () => {
if (!offlineSearch) refetch();
else {
const result = filterResult();
queryClient.setQueryData(queryKey, result);
}
};
function resulLabelHandler() {
const resultSize = items.length;
let registro = 'registro';
let encontrado = 'encontrado';
if (resultSize > 1) {
registro += 's';
encontrado += 's';
}
const defaultText = `${registro} ${encontrado}`;
if (resultSize > 0) return `${resultSize} ${defaultText}`;
else return `Nenhum ${defaultText}`;
}
useEffect(() => {
setSearchResult(items);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
setSearchText('');
refetch().then(({ data }) => {
if (data) {
const items = data.pages.flatMap((page) => page.data);
setSearchResult(items);
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<Modal
open={isOpen}
size='sm'
onClose={() => onClose && onClose()}
header={
<div>
<h4>{title}</h4>
<p>{subTitle}</p>
</div>
}
content={
<>
<form
onSubmit={(e) => {
e.preventDefault();
onSearch();
}}
className='flex gap-2 items-center w-full'
>
<InputWrapper
inputProps={{
startAdornment: <HiOutlineSearch className='text-lg' />,
}}
size='small'
className='w-full'
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
placeholder='Digite para pesquisar'
/>
<Button
size='sm'
data-testid={'btn-search-modal'}
icon={<BsSearch />}
type='submit'
variant='solid'
></Button>
</form>
<div className='mt-4'>
{status === 'success' && (
<p className='font-semibold uppercase text-xs mb-4'>
{resulLabelHandler()}
</p>
)}
<div className='overflow-y-auto h-80 mb-6'>
<ScrollBar data-testid={'list-search-customer'}>
{isLoading ? (
<span>Carregando...</span>
) : typeof children === 'function' ? (
children({ searchText })
) : (
<>
{children}
<Button onClick={() => fetchNextPage()}>
Carregar mais
</Button>
</>
)}
</ScrollBar>
</div>
</div>
</>
}
/>
);
} |
Beta Was this translation helpful? Give feedback.
you probably use that key already for non-infinite queries, see:
https://tkdodo.eu/blog/effective-react-query-keys#caching-data