admin管理员组

文章数量:1129201

I'm working on a GIF search feature similar to Instagram's, where users can search for GIFs and see a list of results. Until each GIF is fully loaded, I want to show a loading spinner for the respective GIF.

Right now, my code fetches GIFs using the Tenor API and displays them in a grid layout. However, I don't have the spinner implementation yet. My goal is to show a spinner for each GIF until it has fully rendered, ensuring a seamless user experience.

Below is my current setup for fetching and displaying GIFs. Can someone guide me on how to implement this behavior efficiently?

The spinner doesn't need to match exactly like instagram's, it could be any simple spinner, the idea is to show a loading state.

import { Box, Group, Image, Skeleton, Stack, TextInput } from '@mantine/core';
import { useDebouncedValue } from '@mantine/hooks';
import { useEffect, useState } from 'react';

const GifSelectorModal = () => {
  const [searchQuery, setSearchQuery] = useState('');
  const [debouncedQuery] = useDebouncedValue(searchQuery, 400);

  const [gifs, setGifs] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  const searchGifs = async (query: string) => {
    const response = await axios.get('', {
      params: {
        q: query,
        key: 'my-key',
        limit: 30,
        client_key: 'tribecrafter',
      },
    });

    return response.data;
  };

  useEffect(() => {
    if (debouncedQuery.length >= 2) {
      setIsLoading(true);

      const fetchGifs = async () => {
        const data = await searchGifs(debouncedQuery);
        setGifs(data.results);
        setIsLoading(false);
      };

      fetchGifs();
    }
  }, [debouncedQuery]);

  return (
    <>
      <TextInput
        value={searchQuery}
        onChange={(e) => setSearchQuery(e.target.value)}
        placeholder="Search GIFs"
      />

      {isLoading ? (
        <Skeletons />
      ) : (
        <Group>
          {gifs.map((gif) => (
            <GifCard key={gif.id} gif={gif} />
          ))}
        </Group>
      )}
    </>
  );
};

const GifCard = ({ gif }) => (
  <Image
    src={gif.media_formats.gif.url}
    alt="GIF"
    onClick={() => console.log('selected gif:', gif)}
  />
);

Desired behaviour:

I tried reading about the onLoad prop for handling when an image has fully loaded, but I’m not sure how to use it in this scenario since I have multiple GIFs loading at the same time. My expectation was to show a spinner for each GIF until it is fully rendered, but currently, all GIFs just appear blank until they finish loading.

I'm working on a GIF search feature similar to Instagram's, where users can search for GIFs and see a list of results. Until each GIF is fully loaded, I want to show a loading spinner for the respective GIF.

Right now, my code fetches GIFs using the Tenor API and displays them in a grid layout. However, I don't have the spinner implementation yet. My goal is to show a spinner for each GIF until it has fully rendered, ensuring a seamless user experience.

Below is my current setup for fetching and displaying GIFs. Can someone guide me on how to implement this behavior efficiently?

The spinner doesn't need to match exactly like instagram's, it could be any simple spinner, the idea is to show a loading state.

import { Box, Group, Image, Skeleton, Stack, TextInput } from '@mantine/core';
import { useDebouncedValue } from '@mantine/hooks';
import { useEffect, useState } from 'react';

const GifSelectorModal = () => {
  const [searchQuery, setSearchQuery] = useState('');
  const [debouncedQuery] = useDebouncedValue(searchQuery, 400);

  const [gifs, setGifs] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  const searchGifs = async (query: string) => {
    const response = await axios.get('https://tenor.googleapis.com/v2/search', {
      params: {
        q: query,
        key: 'my-key',
        limit: 30,
        client_key: 'tribecrafter',
      },
    });

    return response.data;
  };

  useEffect(() => {
    if (debouncedQuery.length >= 2) {
      setIsLoading(true);

      const fetchGifs = async () => {
        const data = await searchGifs(debouncedQuery);
        setGifs(data.results);
        setIsLoading(false);
      };

      fetchGifs();
    }
  }, [debouncedQuery]);

  return (
    <>
      <TextInput
        value={searchQuery}
        onChange={(e) => setSearchQuery(e.target.value)}
        placeholder="Search GIFs"
      />

      {isLoading ? (
        <Skeletons />
      ) : (
        <Group>
          {gifs.map((gif) => (
            <GifCard key={gif.id} gif={gif} />
          ))}
        </Group>
      )}
    </>
  );
};

const GifCard = ({ gif }) => (
  <Image
    src={gif.media_formats.gif.url}
    alt="GIF"
    onClick={() => console.log('selected gif:', gif)}
  />
);

Desired behaviour:

I tried reading about the onLoad prop for handling when an image has fully loaded, but I’m not sure how to use it in this scenario since I have multiple GIFs loading at the same time. My expectation was to show a spinner for each GIF until it is fully rendered, but currently, all GIFs just appear blank until they finish loading.

Share Improve this question edited 2 days ago Drew Reese 202k17 gold badges228 silver badges264 bronze badges asked Jan 8 at 14:32 SujalSujal 231 silver badge5 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I found a solution myself.

const GifCard = ({
  gif,
  onClick
}: {
  gif: Gif;
  onClick: (gif: Gif) => void;
}) => {
  const [isLoading, setIsLoading] = useState(true);

  return (
    <>
      <Skeleton
        w="100%"
        maw={160}
        radius="xs"
        aria-label="gif skeleton"
        h={gif.media_formats.gif.duration > 3 ? 160 : 90}
        style={{ display: isLoading ? 'block' : 'none' }}
      />

      <Image
        src={gif.media_formats.gif.url}
        w="100%"
        maw={160}
        radius="xs"
        alt="GIF"
        onLoad={() => setIsLoading(false)}
        style={{ display: isLoading ? 'none' : 'block' }}
        onClick={() => onClick(gif)}
      />
    </>
  );
};

本文标签: javascriptHow to Implement Loading Spinners for GIF Search Results Like InstagramStack Overflow