Home > other >  React memory leak error (Can't perform a React state update on an unmounted component)
React memory leak error (Can't perform a React state update on an unmounted component)

Time:12-07

Im getting this error mostly while shifting components. Can anyone help me out. I have tried the abortController and mount state solution but none of them worked

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. at FeedVideo

import { FC, useEffect, useState } from 'react';
import ReactPlayer from 'react-player';
import { FeedVideoProps } from '../../utils/types/interfaces';
import { getDecodedMedia } from '../../utils/helpers/getS3URL';

const FeedVideo: FC<FeedVideoProps> = ({ s3Key }: FeedVideoProps) => {
  const [videoLink, setVideoLink] = useState<string>('');
  const [isPlaying, setIsPlaying] = useState<boolean>(true);

  const getURL = async (key: string) => {
    const link: string | object = await getDecodedMedia(key);
    setVideoLink(link as string);
  };

  useEffect(() => {
    const abortController = new AbortController();
    getURL(s3Key).then(() => abortController.abort());
    return () => {
      abortController.abort();
    };
  }, [s3Key]);

  return (
    <ReactPlayer
      stopOnUnmount={true}
      className={'react-player'}
      controls={true}
      url={videoLink}
      playing={isPlaying}
    />
  );
};

export default FeedVideo;

here is the code of the component that im using.

CodePudding user response:

I wouldn't worry much about it, since it's just a warning that React gives you when some state update happens after unmount. In your case, it is happening because getUrl is async and after resolving it sets videoLink.

I'm saying that you shouldn't worry too much because what is happening is that your component is unmounting and then one small operation is "leaking" (which is setVideoLink(link as string)).

Memory leaks are worrisome when you're handling event listeners or intervals.

Even so, if you're worried about this behavior or if you're just too bothered with the warning you could create a logic that checks if your component is mounted before triggering the setState call:

import { FC, useEffect, useState } from 'react';
import ReactPlayer from 'react-player';
import { FeedVideoProps } from '../../utils/types/interfaces';
import { getDecodedMedia } from '../../utils/helpers/getS3URL';

const FeedVideo: FC<FeedVideoProps> = ({ s3Key }: FeedVideoProps) => {
  const [videoLink, setVideoLink] = useState<string>('');
  const [isPlaying, setIsPlaying] = useState<boolean>(true);

  const getURL = async (key: string, isMounted: boolean) => {
    const link: string | object = await getDecodedMedia(key);
    if (isMounted) setVideoLink(link as string);
  };

  useEffect(() => {
    let isMounted = true;
    const abortController = new AbortController();
    getURL(s3Key, isMounted).then(() => abortController.abort());
    return () => {
      abortController.abort();
      isMounted = false;
    };
  }, [s3Key]);

  return (
    <ReactPlayer
      stopOnUnmount={true}
      className={'react-player'}
      controls={true}
      url={videoLink}
      playing={isPlaying}
    />
  );
};

export default FeedVideo;

CodePudding user response:

  const getURL = async (key: string): Promise<string> => {
    try {
      const link: string | object = await getDecodedMedia(key);
      return (link as string) || '';
    } catch (e) {
      throw new Error(e);
    }
  };

  useEffect(() => {
    let feedVideoMounted = true;
    getURL(s3Key).then((link) => {
      if (feedVideoMounted && link) {
        setVideoLink(link);
      }
    });
    return () => {
      feedVideoMounted = false;
    };
  }, [s3Key]);

So, i fixed the issue by changing the logic to this and it worked!

  • Related