简体   繁体   English

功能性反应组件中的全局范围道具

[英]Global scope prop in functional react component

I am using react-native-sound for audio in this component and want to play from a url file that is passed to the component.我在这个组件中使用react-native-sound作为音频,并希望从传递给该组件的 url 文件播放。 The problem is that if the var audio is declared inside the functional component then each time the component renders the variable is created again and this plays the sound file as a new instance and we have same sound playing multiple times on top of each other.问题是,如果在功能组件中声明了 var 音频,那么每次组件呈现变量时都会再次创建该变量,这会将声音文件作为新实例播放,并且我们会在彼此之上多次播放相同的声音。

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
        }
    })

If I move the var audio outside / above the functional component as a global variable it works fine but then I can not pass the component prop aka url to it as the variable is out of the function component scope.如果我将 var 音频作为全局变量移动到功能组件的外部/上方,它可以正常工作,但是我无法将组件 prop aka url传递给它,因为该变量超出了功能组件范围。 How can I pass a prop that keeps reference and does not recreate on each render?如何传递一个保持引用并且不在每次渲染时重新创建的道具?

For example例如

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]);

Wrap in useEffect and have dependency array as [] will run only once or [url] to update when url updates包裹在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]);

Try using useEffect:尝试使用 useEffect:

const audioRef = useRef(null);

useEffect(() => {
   // This will be triggered only once when the component is mounted
   audioRef.current = new Sound(url, null, ...);

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

PD: This code was written on the fly, so further modifications might be needed PD:此代码是即时编写的,因此可能需要进一步修改

This is the correct use case for useRef ( https://reactjs.org/docs/hooks-reference.html#useref )这是useRef的正确用例( https://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
        }
      })
    }
   }, [])


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM