2

react-native-sound在此组件中使用音频,并希望从传递给组件的 url 文件中播放。问题是,如果在功能组件内声明了 var audio,那么每次组件渲染时都会再次创建该变量,这会将声音文件作为新实例播放,并且我们会在彼此之上多次播放相同的声音。

import Sound from "react-native-sound"

var audio = new Sound.. //Works if declared here but cant's pass url prop

const SoundPlayer: FC<SoundProps> = ({ url }) => {
    const [playing, setPlaying] = useState<boolean | null>(null)

    var audio = new Sound(url, null, (error) => {
        if (error) {
            console.log("failed to load the sound", error)
            return
        }
    })

如果我将 var audio 作为全局变量移到功能组件之外/上方,它可以正常工作,但是我不能将组件 prop aka 传递url给它,因为变量超出了功能组件范围。如何传递一个保持引用并且不会在每次渲染时重新创建的道具?

4

4 回答 4

1

尝试使用 useEffect:

const audioRef = useRef(null);
const [duration, setDuration] = useState(0);

useEffect(() => {
   // This will be triggered only once when the component is mounted
   audioRef.current = new Sound(url, null, (error) => {
      if(error) {
         // Here you can implement some retry policy if there was some error loading the sound
         return;
      }

      setDuration(Math.trunc(audioRef.current.getDuration())); 
   });

   return = () => {
     // This will be triggered on component is unmounted
     audioRef.current.release();
   }
}, [audioRef, setDuration]);

PD:此代码是即时编写的,因此可能需要进一步修改

于 2021-10-28T04:54:42.280 回答
1

这是useRefhttps://reactjs.org/docs/hooks-reference.html#useref)的正确用例

import Sound from "react-native-sound"

const SoundPlayer: FC<SoundProps> = ({ url }) => {
    const audioRef = useRef(null); 
    const [playing, setPlaying] = useState<boolean | null>(null)

  // use useEffect to hook on mounted
   useEffect(() => {
    if(audioRef.current === null) {
      audioRef.current = new Sound(url, null, (error) => {
        if (error) {
            console.log("failed to load the sound", error)
            return
        }
      })
    }
   }, [])


于 2021-10-28T05:08:30.870 回答
0

例如

import Sound from "react-native-sound"

var audio;

const SoundPlayer: FC<SoundProps> = ({ url }) => {
    const [playing, setPlaying] = useState<boolean | null>(null)
    
    useEffect(() => {
      audio = new Sound(url, null, (error) => {
          if (error) {
              console.log("failed to load the sound", error)
              return
          }
      })
    }, [url]);
于 2021-10-28T04:46:08.930 回答
0

包裹useEffect并具有依赖数组,因为 [] 将只运行一次或 [url] 在 url 更新时更新

const [audio, setAudio] = useState(null);
useEffect(() => {
  var ado = new Sound(url, null, (error) => {
    if (error) {
      console.log("failed to load the sound", error);
      return;
    }
  });
  setAudio(ado);
}, [url]);
于 2021-10-28T04:47:37.690 回答