skip to Main Content

I have an array of objects like so:

const [categories, setCategories] = React.useState([
    {
      id: 1,
      title: 'Top Picks',
      subTitle: "Today's hottest stuff",
      images: [],
      searchQuery: 'shoes',
    },
...]);

Which I update with values in useEffect once like so:

React.useEffect(() => {

    const newCategories = categories.map(category => {

      fetch(`https://api.pexels.com/v1/search?query=${category.searchQuery}&per_page=10`, {
        headers: {
          'Authorization': apiKey,
        },
      }).then(r => {

        r.json().then(convertedJson => {

          category.images = convertedJson.photos;
        });
      });

      return category;
    });

    setCategories(newCategories);
  }, []);

however the child components here never rerender and I cannot figure out why. My understanding is that .map creates a new array anyhow, so the spread syntax isn’t necessary in setCategories() but regardless it does not work.

{categories.map((category, i) => (
        <CategorySlider {...category} key={i}/>
      ))}

2

Answers


  1. Chosen as BEST ANSWER

    Thanks! Using setState before the promises resolved was indeed the problem. The solution looks like this now:

     React.useEffect(() => {
        async function fetchImages() {
          const promises = categories.map(async category => {
            const response = await fetch(
              `https://api.pexels.com/v1/search?query=${category.searchQuery}&per_page=10`,
              {
                headers: {
                  Authorization: apiKey,
                },
              }
            );
            const convertedJson = await response.json();
            category.images = convertedJson.photos;
            return category;
          });
          setCategories(await Promise.all(promises));
        }
        fetchImages();
      }, []);
    

  2. There’s a few issues but the primary issue I see is you’re returning the category before the fetch can complete – so even when those fetch calls inside your map complete, you already returned the category below before the fetch completes.

    Try using the .finally() block:

    React.useEffect(() => {
    
      const newCategories = categories.map(category => {
        const c = {...category}; // <--- good practice
        fetch(`https://api.pexels.com/v1/search?query=${category.searchQuery}&per_page=10`, {
          headers: {
            'Authorization': apiKey,
          },
        }).then(r => {
          r.json().then(convertedJson => {
            category.images = convertedJson.photos;
          });
        }).catch((err) => {
          console.error(err);
        }).finally(() => {
          return category;
        });
      });
    
      setCategories(newCategories);
    }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search