bamlab / react-tv-space-navigation

A React Native module to handle spatial navigation for a TV application in a 100% cross-platform way
https://bamlab.github.io/react-tv-space-navigation/
MIT License
219 stars 19 forks source link

SpatialNavigationVirtualizedList: Additional Items Not Rendering on Data Fetch #142

Open danilomartinelli opened 4 months ago

danilomartinelli commented 4 months ago

Describe the bug The SpatialNavigationVirtualizedList component does not display more than the initial set of items when fetching additional data on reaching the end of the list. The UI does not render the newly fetched items even though the data is correctly fetched and available.

To Reproduce

import React, { useMemo, useState } from 'react';
import { View } from 'react-native';
import { SpatialNavigationVirtualizedList, SpatialNavigationNode } from 'react-tv-space-navigation';
import DetailedItemCard from './DetailedItemCard';
import { useVideoSearchRepository } from './hooks';

const MyComponent = () => {
  const [queryText, setQueryText] = useState('');

  // queryText is updated based on the input state logic
  // Example: setQueryText(inputValue);

  const {
    rows: videoRows,
    fetchNextPage: fetchNextVideoPage,
  } = useVideoSearchRepository(queryText);

  const memoizedVideoRows = useMemo(() => videoRows || [], [videoRows]);

  console.log(memoizedVideoRows); // Logs 16 items when onEndReached is triggered

  const renderVideoItem = ({ item, index }) => (
    <SpatialNavigationNode
      key={`video-${item.id}-${index}`}
      isFocusable={true}
      onSelect={() => onVideoItemSelected(item)}>
      {({ isFocused }) => (
        <View style={{ backgroundColor: theme.colors.BACKGROUND }}>
          <DetailedItemCard
            item={item}
            isFocused={isFocused}
            width={380}
            height={210}
          />
        </View>
      )}
    </SpatialNavigationNode>
  );

  return (
    <SpatialNavigationVirtualizedList
      data={memoizedVideoRows}
      renderItem={renderVideoItem}
      itemSize={230}
      numberOfRenderedItems={8}
      numberOfItemsVisibleOnScreen={4}
      onEndReachedThresholdItemsNumber={4}
      onEndReached={fetchNextVideoPage}
      orientation="vertical"
    />
  );
};

Expected behavior When the onEndReached function is triggered and new data is fetched, the component should render the additional items. For example, if the initial set of 8 items is displayed, and 8 more items are fetched, the component should then display a total of 16 items.

Screenshots Due to confidentiality terms, I cannot provide screenshots. If necessary, I can recreate the code with alternate names for demonstration purposes. Please feel free to let me know if you need further details or additional context.

Version and OS

Additional context The issue is observed when running the development environment with the target set for web using the command:

webpack serve --env development --config webpack.config.js

Here are additional code snippets for the hook and its respective calls:

const memoizedVideoRows = useMemo(() => videoRows || [], [videoRows]);

const {
  rows: videoRows,
  getItem: getVideoItem,
  fetchNextPage: fetchNextVideoPage,
} = useVideoSearchRepository(queryText);

const renderVideoItem = ({ item, index }) => (
  <SpatialNavigationNode
    key={`video-${item.id}-${index}`}
    isFocusable={true}
    onSelect={() => onVideoItemSelected(item)}>
    {({ isFocused }) => (
      <View style={{ backgroundColor: theme.colors.BACKGROUND }}>
        <DetailedItemCard
          item={item}
          isFocused={isFocused}
          width={380}
          height={210}
        />
      </View>
    )}
  </SpatialNavigationNode>
);

const {
  rows: videoRows,
  fetchNextPage: fetchNextVideoPage,
} = useVideoSearchRepository(queryText);

fetchNextPage: () => fetchNextPage(searchResultData),

const searchResultData = useSearchVideosInfiniteQuery(queryText, 8);

export const useSearchVideosInfiniteQuery = (
  query?: string,
  pageSize?: number,
) => useInfiniteQuery(createSearchVideosInfiniteQuery(query, pageSize));

return {
  queryKey: ['paginated-search-videos-infinite', query, pageSize],
  initialPageParam: 1,
  queryFn: ({ pageParam = 1 }) => {
    if (!query) {
      return Promise.resolve(placeholderSearchPage(pageSize));
    }
    return fetchSearchItems(query, VIDEO_SEARCH_TYPES, pageParam, pageSize);
  },
  getNextPageParam: defaultFecthNextPage,
  enabled: query !== undefined,
};

const fetchSearchItems = async (
  searchQuery: string,
  searchTypes: SearchTypes[],
  page: number = 1,
  pageSize: number | undefined = undefined,
) => {
  return await Brand.siteApiClient.search(
    searchQuery,
    searchTypes,
    page,
    pageSize,
  );
};
pierpo commented 3 months ago

Hey!

Thank you for the detailed issue. I'll give a try to the pagination feature, it's been a while since it was tested (my bad -- there's no working example on that nor any test).

I'll try to do this ASAP (ETA : a week maybe?).

Cheers 🙌

danilomartinelli commented 3 months ago

Hey pierpo! How are you? Any updates? Do you need help with that problem?

pierpo commented 3 months ago

Hey! Sorry I totally forgot to give news on this. I did an example on the project... and it worked well 😱 You can check out this branch: fix/repro-pagination and have a look at the example, see if there is any difference with what you've done 🤔

pierpo commented 1 month ago

Hey @danilomartinelli, did you have a chance to have a look? 😁