功能反应组件中的全局范围道具
Global scope prop in functional react component
我在该组件中使用 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
传递给它,因为变量不在功能组件中范围。我怎样才能传递一个保留引用并且不在每次渲染时重新创建的道具?
例如
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]);
包装在 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]);
尝试使用 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]);
P.D.: 这段代码是即时编写的,因此可能需要进一步修改
这是 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
}
})
}
}, [])
我在该组件中使用 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
传递给它,因为变量不在功能组件中范围。我怎样才能传递一个保留引用并且不在每次渲染时重新创建的道具?
例如
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]);
包装在 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]);
尝试使用 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]);
P.D.: 这段代码是即时编写的,因此可能需要进一步修改
这是 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
}
})
}
}, [])