@@ -19,22 +19,21 @@ const AudioWaveform: React.FC<AudioWaveformProps> = ({
1919
2020 useEffect ( ( ) => {
2121 let mounted = true ;
22-
22+ let ws = wavesurfer . current ;
23+
2324 const initWaveSurfer = async ( ) => {
2425 if ( ! waveformRef . current || ! audioUrl ) return ;
2526
2627 try {
27- // Clean up any existing instance
28- if ( wavesurfer . current ) {
29- try {
30- wavesurfer . current . destroy ( ) ;
31- } catch ( e ) {
32- // Silently ignore destroy errors
33- }
28+ // Clear any existing instance safely
29+ if ( ws ) {
30+ // Instead of immediately destroying, just set to null
31+ // We'll destroy it outside this function
3432 wavesurfer . current = null ;
3533 }
3634
37- wavesurfer . current = WaveSurfer . create ( {
35+ // Create a fresh instance
36+ const newWaveSurfer = WaveSurfer . create ( {
3837 container : waveformRef . current ,
3938 waveColor : "rgba(255, 255, 255, 0.6)" ,
4039 progressColor : "rgba(255, 255, 255, 0.9)" ,
@@ -46,23 +45,36 @@ const AudioWaveform: React.FC<AudioWaveformProps> = ({
4645 interact : false ,
4746 } ) ;
4847
48+ // Assign to ref only if component is still mounted
49+ if ( mounted ) {
50+ wavesurfer . current = newWaveSurfer ;
51+ } else {
52+ // Component unmounted during initialization, clean up
53+ try {
54+ newWaveSurfer . destroy ( ) ;
55+ } catch ( e ) {
56+ // Ignore destroy errors
57+ }
58+ return ;
59+ }
60+
4961 // Event listeners
50- wavesurfer . current . on ( "ready" , ( ) => {
62+ newWaveSurfer . on ( "ready" , ( ) => {
5163 if ( mounted ) {
5264 setIsLoading ( false ) ;
5365 setError ( false ) ;
5466 }
5567 } ) ;
5668
57- wavesurfer . current . on ( "error" , ( err ) => {
69+ newWaveSurfer . on ( "error" , ( err ) => {
5870 console . error ( "WaveSurfer error:" , err ) ;
5971 if ( mounted ) {
6072 setError ( true ) ;
6173 setIsLoading ( false ) ;
6274 }
6375 } ) ;
6476
65- await wavesurfer . current . load ( audioUrl ) ;
77+ await newWaveSurfer . load ( audioUrl ) ;
6678 } catch ( err ) {
6779 console . error ( "Failed to initialize WaveSurfer:" , err ) ;
6880 if ( mounted ) {
@@ -72,27 +84,50 @@ const AudioWaveform: React.FC<AudioWaveformProps> = ({
7284 }
7385 } ;
7486
75- initWaveSurfer ( ) ;
76-
77- return ( ) => {
78- mounted = false ;
79- // Use a safer cleanup approach to avoid AbortError
80- if ( wavesurfer . current ) {
87+ // First safely destroy previous instance if it exists
88+ if ( ws ) {
89+ // Use this pattern to safely destroy the previous instance
90+ const wsToDestroy = ws ;
91+ // Detach from ref immediately
92+ wavesurfer . current = null ;
93+
94+ // Wait a tick to destroy so any pending operations can complete
95+ requestAnimationFrame ( ( ) => {
8196 try {
82- // Wrap in setTimeout to avoid race conditions with AbortController
83- setTimeout ( ( ) => {
84- try {
85- if ( wavesurfer . current ) {
86- wavesurfer . current . destroy ( ) ;
87- wavesurfer . current = null ;
88- }
89- } catch ( e ) {
90- console . warn ( "Error during delayed WaveSurfer cleanup:" , e ) ;
91- }
92- } , 0 ) ;
97+ wsToDestroy . destroy ( ) ;
9398 } catch ( e ) {
94- console . warn ( "Error during WaveSurfer cleanup:" , e ) ;
99+ // Ignore errors during destroy
100+ }
101+ // Only initialize new instance after destroying the old one
102+ if ( mounted ) {
103+ initWaveSurfer ( ) ;
95104 }
105+ } ) ;
106+ } else {
107+ // No previous instance to clean up, initialize directly
108+ initWaveSurfer ( ) ;
109+ }
110+
111+ return ( ) => {
112+ // Mark component as unmounted
113+ mounted = false ;
114+
115+ // Store reference to current wavesurfer instance
116+ const wsToDestroy = wavesurfer . current ;
117+
118+ // Immediately clear the ref to prevent accessing it after unmount
119+ wavesurfer . current = null ;
120+
121+ // If we have an instance to clean up, do it safely
122+ if ( wsToDestroy ) {
123+ // Delay destruction to avoid race conditions
124+ requestAnimationFrame ( ( ) => {
125+ try {
126+ wsToDestroy . destroy ( ) ;
127+ } catch ( e ) {
128+ // Ignore destroy errors - they're expected
129+ }
130+ } ) ;
96131 }
97132 } ;
98133 } , [ audioUrl , height ] ) ;
0 commit comments