ak1394 / react-native-tts

React Native Text-To-Speech library for Android and iOS
601 stars 154 forks source link

listeners calling handler when set on component mount #151

Open pivcec opened 3 years ago

pivcec commented 3 years ago

The listeners that I am setting as soon as component is being mounted are being called multiple times when component mounts.

It seems to me that they should not be called when set.

I'm using debounce to get around that so that only one handler gets called on mount, and I am also checking for a null initial value in the state that I am using to track whether Tts is currently playing:

useEffect(() => {
    const handleSetIsPlaying = (isPlaying) => {
      setIsPlaying((prev) => (prev === null ? null : isPlaying));
    };

    // handle the fact that all three listeners are immediately called when set multiple times by debouncing
    // also check for null, initial value before calling set state for no reason
    const debouncedSetIsPlaying = debounce(handleSetIsPlaying, 1000, {
      leading: true,
      trailing: false,
    });

    const startSubscription = Tts.addEventListener('tts-start', () =>
      debouncedSetIsPlaying(true),
    );
    const finishSubscription = Tts.addEventListener('tts-finish', () =>
      debouncedSetIsPlaying(false),
    );
    const cancelSubscription = Tts.addEventListener('tts-cancel', () =>
      debouncedSetIsPlaying(false),
    );

    return () => {
      Tts.stop();
      startSubscription.remove();
      finishSubscription.remove();
      cancelSubscription.remove();
    };
  }, []);

It's all quite hacky and I am wondering if there can be a better way to handle all of this in general.