Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defer loading to address race condition with event subscriptions #7

Closed
wants to merge 2 commits into from

Conversation

njbair
Copy link

@njbair njbair commented Jun 21, 2024

Regarding this issue I opened in the main branch, I've found a fix for the race condition exposed when using React with pre-calculated peaks.

This PR picks out the { url, peaks, duration } props from the options object on initialization, and passes them to a new hook, useWavesurferLoad to trigger loading after the Wavesurfer instance is attached and all events are subscribed.

For your convenience, I've set up some tests in this demo project. This PR branch is included as a submodule. To set it up: clone the demo repo, run git submodule init, then run npm install && npm start.

When running the demo, you can choose between loading with or without peaks. I've added some buttons to toggle between media files and to increase/decrease the barWidth prop, just to show that this fix does not break/regress any previous functionality.

) {
useEffect(() => {
if (!wavesurfer) return
if (!url) return
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL can be empty, it should still render a silent waveform.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I'll make the update soon and re-push.

@njbair
Copy link
Author

njbair commented Jun 22, 2024

The test was expecting WaveSurfer.create() to be called with--among other things--the url parameter. But this whole PR is about pulling out the url parameter (along with peaks and duration) and calling them later via .load().

I updated the test to not expect url in .toHaveBeenCalledWith().

I also added a thorough example at examples/peaks, to simplify testing instead of using a separate demo repo.

/**
* Wavesurfer player component
* @see https://wavesurfer.xyz/docs/modules/wavesurfer
* @public
*/
const WavesurferPlayer = memo((props: WavesurferProps): ReactElement => {
const containerRef = useRef<HTMLDivElement | null>(null)
const [options, events] = useWavesurferProps(props)
const [{ url, peaks, duration, ...options }, events] = useWavesurferProps(props)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...options will probably create a new object on every render and should be memoized with useMemo.

@katspaugh
Copy link
Owner

katspaugh commented Jun 23, 2024

I've made a PR in the main wavesurfer repo that will most likely fix this: katspaugh/wavesurfer.js#3762

Please let me know if it didn't and we can reopen this PR. Thanks!

@katspaugh katspaugh closed this Feb 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants