LonelyCpp / react-native-youtube-iframe

A wrapper of the Youtube-iframe API built for react native.
https://lonelycpp.github.io/react-native-youtube-iframe/
MIT License
603 stars 153 forks source link

Problem with current video in FlatList #194

Closed Ozzi48 closed 2 years ago

Ozzi48 commented 2 years ago

Describe the bug I have the FlatList with videos and when I use playerRef.current.getDuration() or playerRef.current.getCurrentTime(), the time data are shown only for last video (no matter which video are playing). Why it could happen? How to change 'current' with current video ID or maybe there is another solution? <FlatList style={{ width: width }} contentContainerStyle={{ alignItems: 'center' }} keyExtractor={(item) => item.id.toString()} data={music} renderItem={({ item }) => <YoutubePlayer ref={playerRef} height={150} width={'50%'} play={item.playing} volume={100} videoId={item.videoID} onChangeState={onStateChange} /> } />

LonelyCpp commented 2 years ago

this is because you're using refs in the wrong way. if you have a list of players, you'll have to create a separate ref for each one of them.

in your code snippet, the ref gets assigned to the last video in the flatlist because the last element captures the ref.

Ozzi48 commented 2 years ago

Please, can you provide example? Is it possible to make without creating child component?

LonelyCpp commented 2 years ago

here's an example : https://stackoverflow.com/a/56063129/3262983

Ozzi48 commented 2 years ago

Thank you. It works! However, when I loop const elapsed = await playerRef.current[i].getCurrentTime() I get the error after stopping the loop [Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'playerRef.current[i].getCurrentTime')]. Is it because playerRef use async function (await)? If yes, is it possible to use without await and how?

So, the problem is that now sometimes I get this error [Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'playerRef.current[i].getCurrentTime')] and sometimes I get the normal value. Why it could be?

here's an example : https://stackoverflow.com/a/56063129/3262983

Ozzi48 commented 2 years ago

@LonelyCpp here is code example. It works, but when I press for example first time "play" it shows warning then after some presses again warning. Why it could be?

import React, { useState, useRef, useEffect } from "react";
import { StyleSheet, Text, View, FlatList } from "react-native";
import YoutubePlayer from "react-native-youtube-iframe"
export default function Screen3() {
    const [test, setTest] = useState()
    const [elapsed, setElapsed] = useState()
    const playerRef = useRef();
    playerRef.current = []
    const tooglePlaying = async(id, i, play) => {
        let playing = false
        setTest(test.map(curr => {
            if(id === curr.id) {
                playing = !curr.playing
             return {...curr, playing: !curr.playing}
            } else {
             return curr
            }
          }))
        do {
            const elapsed = await playerRef.current[i].getCurrentTime()
            setElapsed(elapsed)
        }while(playing == true)
      }
    const addToRefs = el => {
        if (el && !playerRef.current.includes(el)) {
          playerRef.current.push(el);
        }
    }
    useEffect(() => {
        setTest(
            [
                {
                    CreatorEmail: "artivejev@gmail.com",
                    eventName: "",
                    id: 23,
                    likes: 3,
                    videoID: "FPOEOq59ONo",
                    videoTitle: "Keanu Silva - King Of My Castle (Don Diablo Edit) (Official Audi",
                    playing: false
                    },
                   {
                    CreatorEmail: "artioejev@gmail.com",
                    eventName: "",
                    id: 22,
                    likes: 3,
                    videoID: "n8p4aUDVeh8",
                    videoTitle: "XXXTENTACION - KING (Lyrics)",
                    playing: false
                  },
                   {
                    CreatorEmail: "artejev@gmail.com",
                    eventName: "",
                    id: 25,
                    likes: 3,
                    videoID: "g_uoH6hJilc",
                    videoTitle: "Years &amp; Years - King (Official Video)",
                    playing: false
                  }
            ]
        )
    }, []);      
    return (
        <View style={styles.container}>
            <Text>{elapsed}</Text>
    <FlatList
        data={test}
        renderItem={({item, index}) => {
            return (
                <View>
                   <Text style={{fontSize: 20, padding: 15, color: "black" }} onPress={() => tooglePlaying(item.id, index, item.playing)}>play</Text>
                   <YoutubePlayer
            ref={addToRefs}
            height={300}
            width={300}
            play={item.playing}
            volume={100}
            videoId={item.videoID}
          />
                </View>
            )
        }}
        keyExtractor={item => item.id.toString()}
      />
        </View>
    );
}
const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: "#fff",
      alignItems: "center",
      justifyContent: "center",
    },
  });
LonelyCpp commented 2 years ago

What warning?

Ozzi48 commented 2 years ago

What warning?

[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'playerRef.current[i].getCurrentTime')] at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch at node_modules\regenerator-runtime\runtime.js:294:29 in invoke at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch at node_modules\regenerator-runtime\runtime.js:155:27 in invoke at node_modules\regenerator-runtime\runtime.js:165:18 in PromiseImpl.resolve.then$argument_0 at node_modules\react-native\node_modules\promise\setimmediate\core.js:37:13 in tryCallOne at node_modules\react-native\node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0 at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:130:14 in _callTimer at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:181:14 in _callImmediatesPass at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:441:30 in callImmediates at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:387:6 in __callImmediates at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:135:6 in guard$argument_0 at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:364:10 in guard at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:134:4 in flushedQueue at [native code]:null in flushedQueue at [native code]:null in callFunctionReturnFlushedQueue

Ozzi48 commented 2 years ago

@LonelyCpp Okey, it was my mistake. I have fixed it and now it works good. Thank you for your help 😄