react-query#useQueries JavaScript Examples

The following examples show how to use react-query#useQueries. 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: hooks.js    From idena-web with MIT License 5 votes vote down vote up
export function useProfileAds() {
  const rpcFetcher = useRpcFetcher()

  const [{profileHash}, {forceUpdate: forceIdentityUpdate}] = useIdentity()

  const {decodeProfile, decodeAd, decodeAdTarget} = useProtoProfileDecoder()

  const {data: profile, status: profileStatus} = useQuery({
    queryKey: ['ipfs_get', [profileHash]],
    queryFn: rpcFetcher,
    enabled: Boolean(profileHash),
    select: decodeProfile,
    staleTime: Infinity,
    notifyOnChangeProps: 'tracked',
  })

  const queryClient = useQueryClient()

  const decodedProfileAds = useQueries(
    profile?.ads?.map(({cid, target, ...ad}) => ({
      queryKey: ['decodedProfileAd', [cid]],
      queryFn: async () => ({
        ...decodeAd(
          await queryClient
            .fetchQuery({
              queryKey: ['ipfs_get', [cid]],
              queryFn: rpcFetcher,
              staleTime: Infinity,
            })
            .catch(() => '')
        ),
        ...decodeAdTarget(target),
        cid,
        ...ad,
      }),
      enabled: Boolean(cid),
      staleTime: Infinity,
    })) ?? []
  )

  const profileAds = useQueries(
    decodedProfileAds
      .filter(({data}) => Boolean(data?.contract))
      .map(({data}) => {
        const {cid, contract, ...ad} = data
        return {
          queryKey: ['profileAd', cid, contract],
          queryFn: async () => ({
            ...ad,
            cid,
            status: AdStatus.Published,
          }),
        }
      })
  )

  const status =
    profileStatus === 'loading' ||
    (profileHash === undefined
      ? true
      : Boolean(profileHash) && profileStatus === 'idle') ||
    decodedProfileAds.some(ad => ad.status === 'loading') ||
    profileAds.some(ad => ad.status === 'loading')
      ? 'loading'
      : 'done'

  return {
    data: profileAds.map(({data}) => data) ?? [],
    status,
    refetch: forceIdentityUpdate,
  }
}
Example #2
Source File: hooks.js    From idena-web with MIT License 4 votes vote down vote up
export function useRotatingAds(limit = 3) {
  const rpcFetcher = useRpcFetcher()

  const burntCoins = useTargetedAds()

  const addresses = [...new Set(burntCoins?.map(({address}) => address))]

  const profileHashes = useQueries(
    addresses.map(address => ({
      queryKey: ['dna_identity', [address]],
      queryFn: rpcFetcher,
      staleTime: 5 * 60 * 1000,
      notifyOnChangeProps: ['data', 'error'],
      select: selectProfileHash,
    }))
  )

  const {decodeAd, decodeProfile} = useProtoProfileDecoder()

  const profiles = useQueries(
    profileHashes.map(({data: cid}) => ({
      queryKey: ['ipfs_get', [cid]],
      queryFn: rpcFetcher,
      enabled: Boolean(cid),
      select: decodeProfile,
      staleTime: Infinity,
      notifyOnChangeProps: ['data'],
    }))
  )

  const profileAdVotings = useQueries(
    profiles
      .map(({data}) => data?.ads)
      .flat()
      .map(ad => ({
        queryKey: ['profileAdVoting', ad?.contract],
        queryFn: () => getAdVoting(ad?.contract),
        enabled: Boolean(ad?.contract),
        staleTime: 5 * 60 * 1000,
        select: data => ({...data, cid: ad?.cid}),
      }))
  )

  const approvedProfileAdVotings = profileAdVotings?.filter(({data}) =>
    isApprovedVoting(data)
  )

  const queryClient = useQueryClient()

  const decodedProfileAds = useQueries(
    burntCoins
      ?.filter(({key}) =>
        approvedProfileAdVotings.some(
          ({data}) => data?.cid === AdBurnKey.fromHex(key).cid
        )
      )
      .slice(0, limit)
      .map(({key, address, amount}) => {
        const {cid} = AdBurnKey.fromHex(key)
        return {
          queryKey: ['decodedRotatingAd', [cid]],
          queryFn: async () => ({
            ...decodeAd(
              await queryClient
                .fetchQuery({
                  queryKey: ['ipfs_get', [cid]],
                  queryFn: rpcFetcher,
                  staleTime: Infinity,
                })
                .catch(() => '')
            ),
            cid,
            author: address,
            amount: Number(amount),
          }),
          enabled: Boolean(cid),
          staleTime: Infinity,
        }
      }) ?? []
  )

  return decodedProfileAds?.map(x => x.data).filter(Boolean) ?? []
}
Example #3
Source File: demo.story.js    From react-table-library with MIT License 4 votes vote down vote up
Demo = () => {
  // dropdown

  const [isDropdownOpen, setDropdownOpen] = React.useState(null);
  const handleDropdownOpen = (event, id) => setDropdownOpen({ element: event.currentTarget, id });
  const handleDropdownClose = () => setDropdownOpen(null);

  // expand

  const [expandedMarketIds, setExpandedMarketIds] = React.useState([]);

  const handleExpand = (incomingId) => {
    const id = incomingId || isDropdownOpen?.id || '';

    if (expandedMarketIds.includes(id)) {
      setExpandedMarketIds(expandedMarketIds.filter((value) => value !== id));
    } else {
      setExpandedMarketIds(expandedMarketIds.concat(id));
    }
  };

  // percentages

  const [percentageUnitOne, setPercentageUnitOne] = React.useState(
    'price_change_percentage_24h_in_currency',
  );

  const [percentageUnitTwo, setPercentageUnitTwo] = React.useState(
    'price_change_percentage_7d_in_currency',
  );

  // watchlist

  const [watched, setWatched] = useLocalStorageState('watched', {
    defaultValue: [],
  });

  // category

  const [activeCategory, setActiveCategory] = React.useState(DEFAULT_CATEGORY);

  // customize

  const [isCustomizeActive, setCustomizeActive] = React.useState(false);
  const [hiddenColumns, setHiddenColumns] = React.useState(Object.keys(CUSTOM_COLUMNS));

  // theming

  const theme = useTheme([CUSTOM_SHARED_THEME, CUSTOM_PRIMARY_THEME]);

  // data

  const [currencies, setCurrencies] = React.useState([]);
  const [fetchState, setFetchState] = React.useState({
    isLoading: false,
    isOverlayLoading: false,
    error: null,
  });

  const fetchCurrencies = async ({ page, size, category }, fetchState) => {
    setFetchState(fetchState);
    setCurrencies(
      await queryClient.fetchQuery(['currencies'], queryCurrencies({ page, size, category })),
    );
    setFetchState({ isLoading: false, isOverlayLoading: false, error: null });
  };

  const marketsData = useQueries(
    expandedMarketIds.map((id) => ({
      queryKey: ['market', id],
      queryFn: queryMarkets(id),
    })),
  );

  const data = {
    nodes: activeCategory === WATCHLIST_CATEGORY ? watched : currencies,
  };

  // pagination

  const pagination = usePagination(
    data,
    {
      state: {
        page: DEFAULT_PAGE,
        size: DEFAULT_SIZE,
      },
      onChange: onPaginationChange,
    },
    {
      isServer: activeCategory === WATCHLIST_CATEGORY ? false : true,
    },
  );

  function onPaginationChange(action, state) {
    fetchCurrencies(
      { page: state.page + 1, size: state.size, category: activeCategory },
      { isOverlayLoading: true },
    );
  }

  // activeCategory

  useCustom('activeCategory', data, {
    state: { activeCategory },
    onChange: onActiveCategoryChange,
  });

  function onActiveCategoryChange(action, state) {
    const size = state.activeCategory === DEFAULT_CATEGORY ? 10 : 50; // TODO

    pagination.fns.onSetPage(DEFAULT_PAGE);
    pagination.fns.onSetSize(size);

    fetchCurrencies(
      {
        page: DEFAULT_PAGE,
        size: size,
        category: state.activeCategory,
      },
      { isOverlayLoading: true },
    );
  }

  // watchlist handler

  const handleFavorite = (item) => {
    if (watched.map((value) => value.id).includes(item.id)) {
      setWatched(watched.filter((value) => value.id !== item.id));
    } else {
      setWatched(watched.concat(item));
    }
  };

  const handleWatchList = () => {
    pagination.fns.onSetPage(DEFAULT_PAGE);
    pagination.fns.onSetSize(DEFAULT_SIZE);

    setActiveCategory(WATCHLIST_CATEGORY);
  };

  // reactive query

  React.useEffect(() => {
    fetchCurrencies(
      {
        page: DEFAULT_PAGE,
        size: DEFAULT_SIZE,
        category: activeCategory,
      },
      { isLoading: true },
    );
  }, [activeCategory]);

  return (
    <>
      <Stack
        direction="row"
        justifyContent="space-between"
        style={{
          borderBottom: '1px solid #D4D4D4',
          overflowX: 'auto',
        }}
      >
        <Stack direction="row" spacing={1} m={1}>
          <Button
            color="secondary"
            size="small"
            variant={activeCategory === WATCHLIST_CATEGORY ? 'outlined' : 'text'}
            startIcon={activeCategory === WATCHLIST_CATEGORY ? <StarIcon /> : <StarOutlineIcon />}
            onClick={handleWatchList}
          >
            Watchlist
          </Button>
          <Button color="secondary" size="small" startIcon={<PieChartIcon />} onClick={() => {}}>
            Portfolio
          </Button>
          <Divider orientation="vertical" flexItem />
          {Object.keys(CATEGORIES).map((key) => (
            <Button
              key={key}
              color="secondary"
              size="small"
              variant={key === activeCategory ? 'outlined' : 'text'}
              onClick={() => setActiveCategory(key)}
            >
              {CATEGORIES[key].label}
            </Button>
          ))}
        </Stack>

        <Stack direction="row" spacing={1} m={1}>
          <Button
            color="secondary"
            size="small"
            variant={isCustomizeActive ? 'outlined' : 'text'}
            onClick={() => setCustomizeActive(!isCustomizeActive)}
          >
            Customize
          </Button>
        </Stack>
      </Stack>

      {isCustomizeActive && (
        <Stack
          direction="row"
          justifyContent="space-between"
          style={{
            borderBottom: '1px solid #D4D4D4',
            overflowX: 'auto',
          }}
        >
          <Stack direction="row" alignItems="center" spacing={1} m={1}>
            <small style={{ textTransform: 'uppercase' }}>Add Columns:</small>

            {Object.keys(CUSTOM_COLUMNS).map((key) => (
              <Button
                key={key}
                color="secondary"
                size="small"
                variant={hiddenColumns.includes(key) ? 'text' : 'outlined'}
                onClick={() =>
                  hiddenColumns.includes(key)
                    ? setHiddenColumns(hiddenColumns.filter((value) => value !== key))
                    : setHiddenColumns(hiddenColumns.concat(key))
                }
              >
                {CUSTOM_COLUMNS[key].label}
              </Button>
            ))}
          </Stack>

          <Stack direction="row" spacing={1} m={1}>
            {hiddenColumns.length < Object.keys(CUSTOM_COLUMNS).length && (
              <Button
                color="secondary"
                size="small"
                onClick={() => setHiddenColumns(Object.keys(CUSTOM_COLUMNS))}
              >
                Clear Columns
              </Button>
            )}
          </Stack>
        </Stack>
      )}

      <div style={{ position: 'relative' }}>
        <Table
          data={data}
          theme={theme}
          layout={{ custom: true, horizontalScroll: true }}
          pagination={pagination}
        >
          {(tableList) => (
            <>
              <Header>
                <HeaderRow>
                  <HeaderCell resize pinLeft />
                  <HeaderCell resize pinLeft>
                    #
                  </HeaderCell>
                  <HeaderCell resize pinLeft>
                    Name
                  </HeaderCell>
                  <HeaderCell resize>Price</HeaderCell>
                  <HeaderCell resize>
                    <StyledSelect
                      value={percentageUnitOne}
                      onChange={(event) => setPercentageUnitOne(event.target.value)}
                    >
                      {Object.keys(PRICE_CHANGE_PERCENTAGE).map((key) => (
                        <MenuItem key={key} value={key}>
                          {PRICE_CHANGE_PERCENTAGE[key].label}
                        </MenuItem>
                      ))}
                    </StyledSelect>
                  </HeaderCell>
                  <HeaderCell resize>
                    <StyledSelect
                      value={percentageUnitTwo}
                      onChange={(event) => setPercentageUnitTwo(event.target.value)}
                    >
                      {Object.keys(PRICE_CHANGE_PERCENTAGE).map((key) => (
                        <MenuItem key={key} value={key}>
                          {PRICE_CHANGE_PERCENTAGE[key].label}
                        </MenuItem>
                      ))}
                    </StyledSelect>
                  </HeaderCell>
                  <HeaderCell resize>Market Cap</HeaderCell>
                  <HeaderCell resize>Circulating Supply</HeaderCell>
                  <HeaderCell resize={hiddenColumns.length !== Object.keys(CUSTOM_COLUMNS).length}>
                    Last 7 Days
                  </HeaderCell>
                  {Object.keys(CUSTOM_COLUMNS).map((column) => (
                    <HeaderCell
                      key={column}
                      resize
                      hide={hiddenColumns.includes(column)}
                      className="small"
                    >
                      <AlignCenter>
                        {CUSTOM_COLUMNS[column].label}&nbsp;
                        <IconButton
                          size="small"
                          onClick={() => setHiddenColumns(hiddenColumns.concat(column))}
                        >
                          <CloseIcon />
                        </IconButton>
                      </AlignCenter>
                    </HeaderCell>
                  ))}
                  <HeaderCell pinRight />
                </HeaderRow>
              </Header>

              <Body>
                {tableList.map((item) => {
                  const marketData = marketsData?.find(
                    (market) => market?.data?.name.toLowerCase() === item.id.toLowerCase(),
                  );

                  return (
                    <React.Fragment key={item.id}>
                      <Row item={item}>
                        <Cell pinLeft>
                          <Tooltip title="Add to Main Watchlist" arrow>
                            <IconButton size="small" onClick={() => handleFavorite(item)}>
                              {watched.map((value) => value.id).includes(item.id) ? (
                                <StarIcon fontSize="small" />
                              ) : (
                                <StarOutlineIcon fontSize="small" />
                              )}
                            </IconButton>
                          </Tooltip>
                        </Cell>
                        <Cell pinLeft>{item.market_cap_rank}</Cell>
                        <Cell pinLeft>
                          <AlignCenter>
                            <img alt="icon" src={item.image} width={20} height={20} />
                            <Ellipse>
                              &nbsp;{item.name}&nbsp;
                              <span style={{ color: '#808a9d' }}>{item.symbol.toUpperCase()}</span>
                            </Ellipse>
                          </AlignCenter>
                        </Cell>
                        <Cell>
                          {item.current_price.toLocaleString('en-US', {
                            style: 'currency',
                            currency: 'USD',
                          })}
                        </Cell>
                        <Cell>
                          <Indicator value={twoDecimals(item[percentageUnitOne])} suffix="%" />
                        </Cell>
                        <Cell>
                          <Indicator value={twoDecimals(item[percentageUnitTwo])} suffix="%" />
                        </Cell>
                        <Cell>
                          {item.market_cap.toLocaleString('en-US', {
                            style: 'currency',
                            currency: 'USD',
                          })}
                        </Cell>
                        <Cell>
                          {item.circulating_supply} {item.symbol.toUpperCase()}
                          {item.max_supply && (
                            <LinearProgress
                              variant="determinate"
                              value={twoDecimals((item.circulating_supply / item.max_supply) * 100)}
                            />
                          )}
                        </Cell>
                        <Cell>
                          <Sparklines data={item.sparkline_in_7d.price} height={40}>
                            <SparklinesLine color="#439867" />
                          </Sparklines>
                        </Cell>
                        {Object.keys(CUSTOM_COLUMNS).map((column) => (
                          <Cell
                            key={column}
                            hide={hiddenColumns.includes(column)}
                            className="small"
                          >
                            {CUSTOM_COLUMNS[column].render(item)}
                          </Cell>
                        ))}
                        <Cell pinRight>
                          <ViewMarket
                            marketData={marketData}
                            item={item}
                            isExpanded={expandedMarketIds.includes(item.id)}
                            onOpen={handleDropdownOpen}
                            onClose={handleExpand}
                          />
                        </Cell>
                      </Row>

                      {marketData?.isFetched && expandedMarketIds.includes(item.id) && (
                        <MarketsTable
                          data={{
                            nodes: marketData?.data.tickers || [],
                          }}
                          hiddenColumns={hiddenColumns}
                        />
                      )}
                    </React.Fragment>
                  );
                })}
              </Body>
            </>
          )}
        </Table>
      </div>

      {fetchState.isLoading && <Loading />}
      {fetchState.isOverlayLoading && <OverlayLoading />}

      <TablePagination
        count={
          activeCategory === WATCHLIST_CATEGORY ? data.nodes.length : 9688 // TODO API does not offer this number
        }
        page={pagination.state.page}
        rowsPerPage={pagination.state.size}
        rowsPerPageOptions={activeCategory === DEFAULT_CATEGORY ? [10, 25, 50, 100] : [50]} // TODO
        onRowsPerPageChange={(event) => pagination.fns.onSetSize(parseInt(event.target.value, 10))}
        onPageChange={(event, page) => pagination.fns.onSetPage(page)}
      />

      <Menu
        anchorEl={isDropdownOpen?.element}
        open={!!isDropdownOpen}
        onClose={handleDropdownClose}
        onClick={handleDropdownClose}
      >
        <MenuItem onClick={() => handleExpand()}>View Markets</MenuItem>
      </Menu>
    </>
  );
}