@apollo/client#NetworkStatus TypeScript Examples

The following examples show how to use @apollo/client#NetworkStatus. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Overview.tsx    From keycapsets.com with GNU General Public License v3.0 5 votes vote down vote up
function Images(props: any): JSX.Element {
    const [atBottom, setIsAtBottom] = useState<boolean>(false);
    const setUserWants = useStore((state) => state.setUserWants);
    const filters = useStore((state) => state.filters);

    const { data, networkStatus, loading, fetchMore } = useQuery(FETCH_KEYCAPSET_QUERY, {
        variables: {
            filter: filters,
            limit: 12,
            offset: 0,
        },
        notifyOnNetworkStatusChange: true,
        fetchPolicy: 'cache-and-network',
    });

    // TODO find way to implement this on cache
    const { data: userWantSetsResponse, loading: userWantsLoading } = useQuery(USER_WANTS_SETS, {
        fetchPolicy: 'network-only',
    });

    useEffect(() => {
        if (!userWantsLoading) {
            setUserWants(userWantSetsResponse.userWantsSets);
        }
    }, [userWantSetsResponse]);

    useEffect(function initializeView() {
        const isBrowser = typeof window !== `undefined`;
        if (isBrowser) {
            window.addEventListener('scroll', checkIsBottomPage);
            return () => window.removeEventListener('scroll', checkIsBottomPage);
        }
    }, []);

    useEffect(
        function handleLoadMore() {
            if (atBottom) {
                if (!loading) {
                    loadMore(data.keycapsets.length || 0);
                }
            }
        },
        [atBottom]
    );

    function checkIsBottomPage() {
        const DELIMITER: number = 132;
        const currentY: number = window.scrollY;
        const docHeight: number = document.body.clientHeight;
        const alreadyScrolled = currentY + window.innerHeight;
        const isAtBottom: boolean = alreadyScrolled > docHeight - DELIMITER;
        setIsAtBottom(isAtBottom);
    }

    function loadMore(offset: number) {
        setIsAtBottom(false);
        return fetchMore({
            variables: {
                limit: 12,
                offset,
            },
            updateQuery: (prev, { fetchMoreResult }) => {
                if (!fetchMoreResult && !fetchMoreResult.keycapsets) return prev;
                return Object.assign({}, prev, {
                    keycapsets: [...prev.keycapsets, ...fetchMoreResult.keycapsets],
                });
            },
        });
    }

    return (
        <div className="overview">
            {data && <Cards keycapsets={data.keycapsets} />}
            {networkStatus === NetworkStatus.fetchMore && <LoadingKeyboardIllustration scale={0.4} />}
        </div>
    );
}
Example #2
Source File: FeaturedProductList.tsx    From magento_react_native_graphql with MIT License 5 votes vote down vote up
FeaturedProductList = ({
  name,
  categoryId,
}: Props): React.ReactElement => {
  const { data, networkStatus, error } = useCategoryProducts({ categoryId });
  const { theme } = useContext(ThemeContext);
  const navigation = useNavigation();

  const onProductItemClicked = (index: number) => {
    if (data?.products?.items) {
      navigation.navigate(Routes.NAVIGATION_TO_PRODUCT_DETAILS_SCREEN, {
        name: data.products.items[index].name,
        sku: data.products.items[index].sku,
      });
    }
  };

  const renderItem = ({
    item,
    index,
  }: {
    item: ProductInListType;
    index: number;
  }) => {
    return (
      <ProductListItem
        item={item}
        index={index}
        horizontalMode
        onPress={onProductItemClicked}
      />
    );
  };

  if (error?.message) {
    return (
      <View>
        <Text>{error.message}</Text>
      </View>
    );
  }

  if (networkStatus === NetworkStatus.loading) {
    return (
      <View style={styles.loadingBox(theme)}>
        <Spinner />
      </View>
    );
  }

  return (
    <View style={styles.container(theme)}>
      {name && (
        <Text h2 h2Style={styles.title}>
          {name}
        </Text>
      )}
      <FlatList
        horizontal
        showsHorizontalScrollIndicator={false}
        data={data?.products?.items ?? []}
        renderItem={renderItem}
        keyExtractor={item => `productListItem${item.sku}`}
      />
    </View>
  );
}
Example #3
Source File: useInfiniteGrid.ts    From atlas with GNU General Public License v3.0 4 votes vote down vote up
useInfiniteGrid = <
  TRawData,
  TPaginatedData extends PaginatedData<unknown>,
  TArgs extends PaginatedDataArgs
>({
  query,
  dataAccessor,
  isReady,
  targetRowsCount,
  itemsPerRow,
  skipCount,
  onScrollToBottom,
  onError,
  queryVariables,
  onDemand,
  onDemandInfinite,
  activatedInfinteGrid,
}: UseInfiniteGridParams<TRawData, TPaginatedData, TArgs>): UseInfiniteGridReturn<TPaginatedData> => {
  const targetDisplayedItemsCount = targetRowsCount * itemsPerRow
  const targetLoadedItemsCount = targetDisplayedItemsCount + skipCount

  const queryVariablesRef = useRef(queryVariables)

  const {
    loading,
    data: rawData,
    error,
    fetchMore,
    refetch,
    networkStatus,
  } = useQuery<TRawData, TArgs>(query, {
    notifyOnNetworkStatusChange: true,
    skip: !isReady,
    variables: {
      ...queryVariables,
      first: targetDisplayedItemsCount + PREFETCHED_ITEMS_COUNT,
    },
    onError,
  })

  const data = dataAccessor(rawData)

  const loadedItemsCount = data?.edges.length ?? 0
  const allItemsLoaded = data ? !data.pageInfo.hasNextPage : false
  const endCursor = data?.pageInfo.endCursor

  // handle fetching more items
  useEffect(() => {
    if (loading || error || !isReady || !fetchMore || allItemsLoaded) {
      return
    }

    const missingItemsCount = targetLoadedItemsCount - loadedItemsCount

    if (missingItemsCount <= 0) {
      return
    }

    fetchMore({
      variables: { ...queryVariables, first: missingItemsCount + PREFETCHED_ITEMS_COUNT, after: endCursor },
    })
  }, [
    loading,
    error,
    fetchMore,
    allItemsLoaded,
    queryVariables,
    targetLoadedItemsCount,
    loadedItemsCount,
    endCursor,
    isReady,
  ])

  useEffect(() => {
    if (!isEqual(queryVariablesRef.current, queryVariables)) {
      queryVariablesRef.current = queryVariables
      refetch()
    }
  }, [queryVariables, refetch])

  // handle scroll to bottom
  useEffect(() => {
    if (onDemand || (onDemandInfinite && !activatedInfinteGrid)) {
      return
    }
    if (error) return

    const scrollHandler = debounce(() => {
      const scrolledToBottom =
        window.innerHeight + document.documentElement.scrollTop >= document.documentElement.offsetHeight
      if (onScrollToBottom && scrolledToBottom && isReady && !loading && !allItemsLoaded) {
        onScrollToBottom()
      }
    }, 100)

    window.addEventListener('scroll', scrollHandler)
    return () => window.removeEventListener('scroll', scrollHandler)
  }, [error, isReady, loading, allItemsLoaded, onScrollToBottom, onDemand, onDemandInfinite, activatedInfinteGrid])

  const edges = data?.edges

  const isRefetching = networkStatus === NetworkStatus.refetch

  const displayedEdges = edges?.slice(skipCount, targetLoadedItemsCount) ?? []
  const displayedItems = isRefetching ? [] : displayedEdges.map((edge) => edge.node)

  const displayedItemsCount = data
    ? Math.min(targetDisplayedItemsCount, data.totalCount - skipCount)
    : targetDisplayedItemsCount
  const placeholdersCount = isRefetching ? targetDisplayedItemsCount : displayedItemsCount - displayedItems.length

  return {
    displayedItems,
    placeholdersCount,
    allItemsLoaded,
    error,
    loading,
    totalCount: data?.totalCount || 0,
  }
}
Example #4
Source File: GithubRepos.tsx    From amplication with Apache License 2.0 4 votes vote down vote up
function GitRepos({
  applicationId,
  gitOrganizationId,
  onGitRepositoryConnected,
  gitProvider,
}: Props) {
  const { trackEvent } = useTracking();

  const {
    data,
    error,
    loading: loadingRepos,
    refetch,
    networkStatus,
  } = useQuery<{
    remoteGitRepositories: RemoteGitRepository[];
  }>(FIND_GIT_REPOS, {
    variables: {
      gitOrganizationId,
      gitProvider,
    },
    notifyOnNetworkStatusChange: true,
  });

  const [connectGitRepository, { error: errorUpdate }] = useMutation(
    CONNECT_GIT_REPOSITORY
  );
  const handleRepoSelected = useCallback(
    (data: RemoteGitRepository) => {
      connectGitRepository({
        variables: {
          gitOrganizationId,
          appId: applicationId,
          name: data.name,
        },
      }).catch(console.error);
      trackEvent({
        eventName: "selectGitRepo",
      });
      onGitRepositoryConnected();
    },
    [
      applicationId,
      connectGitRepository,
      gitOrganizationId,
      onGitRepositoryConnected,
      trackEvent,
    ]
  );
  const handleRefresh = useCallback(() => {
    refetch();
  }, [refetch]);

  const errorMessage = formatError(error || errorUpdate);

  return (
    <div className={CLASS_NAME}>
      <div className={`${CLASS_NAME}__header`}>
        <h4>
          Select a {gitProvider} repository to sync your application with.
        </h4>
        {loadingRepos || networkStatus === NetworkStatus.refetch ? (
          <CircularProgress />
        ) : (
          <Tooltip aria-label="Refresh repositories" direction="w" noDelay wrap>
            <Button
              buttonStyle={EnumButtonStyle.Clear}
              onClick={(e) => {
                handleRefresh();
              }}
              type="button"
              icon="refresh_cw"
            />
          </Tooltip>
        )}
      </div>
      {networkStatus !== NetworkStatus.refetch && // hide data if refetch
        data?.remoteGitRepositories?.map((repo) => (
          <GitRepoItem
            key={repo.fullName}
            repo={repo}
            onSelectRepo={handleRepoSelected}
          />
        ))}
      <Snackbar open={Boolean(error || errorUpdate)} message={errorMessage} />
    </div>
  );
}
Example #5
Source File: ProductListScreen.tsx    From magento_react_native_graphql with MIT License 4 votes vote down vote up
ProductListScreen = ({
  navigation,
  route: {
    params: { categoryId },
  },
}: Props): React.ReactElement => {
  const { data, networkStatus, error, refresh, loadMore } = useCategoryProducts(
    {
      categoryId,
    },
  );
  const { isVisible, selectedIndex, setVisible, sortOptions } = useSort({
    onPress: refresh,
  });
  const { theme } = useContext(ThemeContext);

  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <CustomHeaderButtons>
          <CustomHeaderItem
            title={translate('common.sort')}
            iconName="sort"
            onPress={() => setVisible(true)}
          />
        </CustomHeaderButtons>
      ),
    });
  }, [navigation]);

  const onProductItemClicked = (index: number) => {
    if (data?.products?.items) {
      navigation.navigate(Routes.NAVIGATION_TO_PRODUCT_DETAILS_SCREEN, {
        name: data.products.items[index].name,
        sku: data.products.items[index].sku,
      });
    }
  };

  const renderItem = ({
    item,
    index,
  }: {
    item: ProductInListType;
    index: number;
  }) => {
    return (
      <ProductListItem
        item={item}
        index={index}
        onPress={onProductItemClicked}
      />
    );
  };

  const renderFooterComponent = () =>
    (networkStatus === NetworkStatus.fetchMore && (
      <View style={styles.footerContainer}>
        <Spinner />
      </View>
    )) || <></>;

  return (
    <GenericTemplate errorMessage={error?.message}>
      <FlatList
        numColumns={2}
        data={data?.products?.items ?? []}
        renderItem={renderItem}
        keyExtractor={item => `productListItem${item.sku}`}
        refreshControl={
          <RefreshControl
            refreshing={
              networkStatus === NetworkStatus.refetch ||
              networkStatus === NetworkStatus.loading
            }
            onRefresh={refresh}
          />
        }
        onEndReached={loadMore}
        ListFooterComponent={renderFooterComponent}
      />
      <BottomSheet isVisible={isVisible} containerStyle={styles.sortContainer}>
        {sortOptions.map((option, index) => (
          <ListItem
            key={option.title}
            containerStyle={[
              option.containerStyle,
              selectedIndex === index && {
                backgroundColor: theme.colors?.grey5,
              },
            ]}
            onPress={option.onPress}
          >
            <ListItem.Content>
              <ListItem.Title style={option.titleStyle}>
                {option.title}
              </ListItem.Title>
            </ListItem.Content>
          </ListItem>
        ))}
      </BottomSheet>
    </GenericTemplate>
  );
}
Example #6
Source File: SearchScreen.tsx    From magento_react_native_graphql with MIT License 4 votes vote down vote up
SearchScreen = ({ navigation }: Props): React.ReactElement => {
  const {
    searchText,
    handleChange,
    networkStatus,
    called,
    loadMore,
    data: { products: { items: products = [] } = {} } = {},
  } = useSearch();
  const { theme } = useContext(ThemeContext);
  const loadingProps = useMemo(() => ({ color: theme.colors?.primary }), [
    theme,
  ]);

  const handleBackPress = () => navigation.pop();

  const onProductItemClicked = (index: number) => {
    navigation.navigate(Routes.NAVIGATION_TO_PRODUCT_DETAILS_SCREEN, {
      name: products[index].name,
      sku: products[index].sku,
    });
  };

  const renderItem = ({
    item,
    index,
  }: {
    item: ProductInListType;
    index: number;
  }) => {
    return (
      <ProductListItem
        item={item}
        index={index}
        onPress={onProductItemClicked}
      />
    );
  };

  // FIXME: Don't show when previous search result was empty, and user is typing
  // create a separate state
  const renderEmptyComponent = () =>
    (searchText.length >= LIMITS.searchTextMinLength &&
      products.length === 0 &&
      called &&
      networkStatus !== NetworkStatus.loading && (
        <View style={styles.center}>
          <Text>
            {translate('searchScreen.noProductsFound', { searchText })}
          </Text>
        </View>
      )) || <></>;

  const renderFooterComponent = () =>
    (networkStatus === NetworkStatus.fetchMore && (
      <View style={styles.footerContainer}>
        <Spinner />
      </View>
    )) || <></>;

  return (
    <GenericTemplate>
      <SearchBar
        placeholder={translate('searchScreen.searchBarHint')}
        onChangeText={handleChange}
        value={searchText}
        showLoading={networkStatus === NetworkStatus.loading}
        searchIcon={{
          name: 'arrow-back',
          onPress: handleBackPress,
        }}
        loadingProps={loadingProps}
        containerStyle={styles.searchBarContainer}
      />
      <FlatList
        numColumns={2}
        data={products}
        renderItem={renderItem}
        keyExtractor={item => `productListItem${item.sku}`}
        ListEmptyComponent={renderEmptyComponent}
        ListFooterComponent={renderFooterComponent}
        onEndReached={loadMore}
      />
    </GenericTemplate>
  );
}