0

I'm working on a component that adds images to items. You can either upload your own image or pick an image, loaded from an API based on the name of the item.

Here is the root component:

const AddMedia = (props) => {
  const [currentTab, setCurrentTab] = useState(0);
  const [itemName, setItemName] = useState(props.itemName);

  return (
    <div>
      <Tabs
        value={currentTab}
        onChange={() => setCurrentTab(currentTab === 0 ? 1 : 0)}
      />
      <div hidden={currentTab !== 0}>
        <FileUpload />
      </div>
      <div hidden={currentTab !== 1}>
        {currentTab === 1 && <ImagePicker searchTerm={itemName} />}
      </div>
    </div>
  );
};

And here is the <ImagePicker />:

import React, { useState, useEffect } from "react";

function ImagePicker({ searchTerm, ...props }) {
  const [photos, setPhotos] = useState([]);

  const searchForImages = async (keyword) => {
    const images = await api.GetImagesByKeyword(keyword);

    return images;
  };

  useEffect(() => {
    const result = searchForImages(searchTerm);
    setPhotos(result);
  }, []);

  return (
    <>
      {photos.map(({ urls: { small } }, j) => (
        <img alt={j} src={small} className={classes.img} />
      ))}
    </>
  );
}

const areSearchTermsEqual = (prev, next) => {
  return prev.searchTerm === next.searchTerm;
};

const MemorizedImagePicker = React.memo(ImagePicker, areSearchTermsEqual);
export default MemorizedImagePicker;

What I'm struggling with is getting the component to not fetch the results again if the searchTerm hasn't changed. For example, when the component loads it's on tab 0 (upload image), you switch to tab 1 (pick an image) and it fetches the results for searchTerm, then you switch to 0 and again to 1 and it fetches them again, although the searchTerm hasn't changed. As you can see, I tried using React.memo but to no avail. Also, I added the currentTab === 1 to stop it from fetching the photos when the root component renders and fetch them only if the active tab is 1.

tdranv
  • 1,140
  • 11
  • 38

1 Answers1

0

You should add the searchTerm as dependency of the useEffect so that it will not fetch again if searchTerm hasn't change:

 useEffect(() => {
    const result = searchForImages(searchTerm);
    setPhotos(result);
  }, [searchTerm]);

Additional information, if you are using eslint to lint your code, you can use the react-hooks/exhaustive-deps rule to avoid this kind of mistake.

Striped
  • 2,544
  • 3
  • 25
  • 31
  • I "chopped off" a big chunk from the component for clarification. It already has it as a dependency. I'm sorry. – tdranv Nov 08 '20 at 09:05
  • 1
    You should edit your post and add it, this is important and people won't understand :) – Striped Nov 08 '20 at 10:20