Skip to content

Commit ba645eb

Browse files
committed
Use ref for playList and videoId
1 parent 9b8f7a9 commit ba645eb

File tree

1 file changed

+43
-30
lines changed

1 file changed

+43
-30
lines changed

src/YoutubeIframe.js

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
1+
import {EventEmitter} from 'events';
12
import React, {
2-
useRef,
3-
useState,
4-
useEffect,
53
forwardRef,
64
useCallback,
5+
useEffect,
76
useImperativeHandle,
87
useMemo,
8+
useRef,
9+
useState,
910
} from 'react';
10-
import {View, StyleSheet, Platform} from 'react-native';
11-
import {WebView} from './WebView';
11+
import {Platform, StyleSheet, View} from 'react-native';
1212
import {
13+
CUSTOM_USER_AGENT,
14+
DEFAULT_BASE_URL,
1315
PLAYER_ERROR,
1416
PLAYER_STATES,
15-
DEFAULT_BASE_URL,
16-
CUSTOM_USER_AGENT,
1717
} from './constants';
18-
import {EventEmitter} from 'events';
1918
import {
20-
playMode,
21-
soundMode,
2219
MAIN_SCRIPT,
2320
PLAYER_FUNCTIONS,
21+
playMode,
22+
soundMode,
2423
} from './PlayerScripts';
24+
import {WebView} from './WebView';
25+
26+
const deepComparePlayList = (lastPlayList, playList) => {
27+
return (
28+
typeof lastPlayList === typeof playList &&
29+
(Array.isArray(lastPlayList)
30+
? lastPlayList.join('')
31+
: lastPlayList === Array.isArray(playList)
32+
? playList.join('')
33+
: playList)
34+
);
35+
};
2536

2637
const YoutubeIframe = (props, ref) => {
2738
const {
@@ -41,7 +52,7 @@ const YoutubeIframe = (props, ref) => {
4152
onError = _err => {},
4253
onReady = _event => {},
4354
playListStartIndex = 0,
44-
initialPlayerParams = {},
55+
initialPlayerParams,
4556
allowWebViewZoom = false,
4657
forceAndroidAutoplay = false,
4758
onChangeState = _event => {},
@@ -50,6 +61,10 @@ const YoutubeIframe = (props, ref) => {
5061
onPlaybackRateChange = _playbackRate => {},
5162
} = props;
5263

64+
const lastVideoIdRef = useRef(videoId);
65+
const lastPlayListRef = useRef(playList);
66+
const initialPlayerParamsRef = useRef(initialPlayerParams || {});
67+
5368
const webViewRef = useRef(null);
5469
const eventEmitter = useRef(new EventEmitter());
5570
const [playerReady, setPlayerReady] = useState(0);
@@ -127,38 +142,37 @@ const YoutubeIframe = (props, ref) => {
127142
}, [play, playerReady, mute, volume, playbackRate]);
128143

129144
useEffect(() => {
130-
if (playerReady < 1) {
145+
if (playerReady < 1 || lastVideoIdRef.current === videoId) {
131146
// no instance of player is ready
147+
// or videoId has not changed
132148
return;
133149
}
134150

151+
lastVideoIdRef.current = videoId;
152+
135153
webViewRef.current.injectJavaScript(
136154
PLAYER_FUNCTIONS.loadVideoById(videoId, play),
137155
);
138-
// We do not need `play` prop because we should not
139-
// recall the load function when the prop changes
140-
// eslint-disable-next-line react-hooks/exhaustive-deps
141-
}, [videoId, playerReady]);
156+
}, [videoId, play, playerReady]);
142157

143158
useEffect(() => {
144159
if (playerReady < 1) {
145160
// no instance of player is ready
146161
return;
147162
}
148163

149-
if (!playList) {
164+
// Also, right now, we are helping users by doing "deep" comparisons of playList prop,
165+
// but in the next major we should leave the responsibility to user (either via useMemo or moving the array outside)
166+
if (!playList || deepComparePlayList(lastPlayListRef.current, playList)) {
150167
return;
151168
}
152169

170+
lastPlayListRef.current = playList;
171+
153172
webViewRef.current.injectJavaScript(
154173
PLAYER_FUNCTIONS.loadPlaylist(playList, playListStartIndex, play),
155174
);
156-
// We do not need `play` and `playListStartIndex` props because we should not
157-
// recall the load function when the props changes
158-
// Also, right now, we are helping users by doing "deep" comparisons of playList prop,
159-
// but in the next major we should leave the responsibility to user (either via useMemo or moving the array outside)
160-
// eslint-disable-next-line react-hooks/exhaustive-deps
161-
}, [Array.isArray(playList) ? playList.join('') : playList, playerReady]);
175+
}, [playList, play, playListStartIndex, playerReady]);
162176

163177
const onWebMessage = useCallback(
164178
event => {
@@ -222,9 +236,9 @@ const YoutubeIframe = (props, ref) => {
222236

223237
const source = useMemo(() => {
224238
const ytScript = MAIN_SCRIPT(
225-
videoId,
226-
playList,
227-
initialPlayerParams,
239+
lastVideoIdRef.current,
240+
lastPlayListRef.current,
241+
initialPlayerParamsRef.current,
228242
allowWebViewZoom,
229243
contentScale,
230244
);
@@ -241,9 +255,6 @@ const YoutubeIframe = (props, ref) => {
241255
const data = ytScript.urlEncodedJSON;
242256

243257
return {uri: base + '?data=' + data};
244-
// videoId, playlist, initialPlayerParams are only used once when initializing YT.Player instance
245-
// further changes are handled by injectJavaScript
246-
// eslint-disable-next-line react-hooks/exhaustive-deps
247258
}, [useLocalHTML, contentScale, baseUrlOverride, allowWebViewZoom]);
248259

249260
return (
@@ -255,7 +266,9 @@ const YoutubeIframe = (props, ref) => {
255266
style={[styles.webView, webViewStyle]}
256267
mediaPlaybackRequiresUserAction={false}
257268
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
258-
allowsFullscreenVideo={!initialPlayerParams?.preventFullScreen}
269+
allowsFullscreenVideo={
270+
!initialPlayerParamsRef.current.preventFullScreen
271+
}
259272
userAgent={
260273
forceAndroidAutoplay
261274
? Platform.select({android: CUSTOM_USER_AGENT, ios: ''})

0 commit comments

Comments
 (0)