0

So I have built app which takes value from input -> set it to the state-> state change triggers functions in useEffect (this part is in custom hook) -> functions fetch data from api -> which triggers functions in useEffect in component to store data in array. The thing is that there are two problems that I am trying to solve :

  1. When user is putting the same value in input and setting it in state it's not triggering useEffect functions (I solved it by wrapping value in object but I am looking for better solution).

  2. When user uses the same value in short period of time api will send the same data which again makes problem with triggering function with useEffect (I tried to solved with refresh state that you will see in code below, but it looks awful)

The question is how can I actually do it properly? Or maybe the solutions I found aren't as bad as I think they are. Thanks for your help.

component

const [nextLink, setNextLink] = useState({ value: "" });
const isMounted = useRef(false);
const inputRef = useRef(null);
const { shortLink, loading, error, refresh } = useFetchLink(nextLink);

const handleClick = () => {
  setNextLink({ value: inputRef.current.value }); 
};

useEffect(() => {
  setLinkArr((prev) => [
    ...prev,
    {
      id: prev.length === 0 ? 1 : prev[prev.length - 1].id + 1,
      long: nextLink.value,
      short: shortLink,
    },
  ]);
  if (isMounted.current) {
    scrollToLink();
  } else {
    isMounted.current = true;
  }
  inputRef.current.value = "";
}, [refresh]);

custom hook

const useFetchLink = (linkToShorten) => {
  const [shortLink, setShortLink] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [refresh, setRefresh] = useState(false); 
  const isMounted = useRef(false);

  const fetchLink = async (link) => {
    setLoading(true);
    try {
      const response = await fetch(
        `https://api.shrtco.de/v2/shorten?url=${link}`
      );
      if (response.ok) {
        const data = await response.json();
        setShortLink(data.result.short_link);
        setRefresh((prev) => !prev);
      } else {
        throw response.status;
      }
    } catch (err) {
      setError(err);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (isMounted.current) {
      if (checkLink(linkToShorten.value)) {
        setError(checkLink(linkToShorten.value));
      } else {
        fetchLink(linkToShorten.value);
      }
    } else {
      isMounted.current = true;
    }
  }, [linkToShorten]);

  const value = { shortLink, loading, error, refresh };
  return value;
};

export default useFetchLink;

0 Answers0