javascript - onViewableItemsChanged is being called even after navigating to different screen in react native flatlist - Stack O

I'm facing an issue with the onViewableItemsChanged prop from the flat-list. I have a list of vide

I'm facing an issue with the onViewableItemsChanged prop from the flat-list. I have a list of videos that are being played when a single video es viewable on the screen, I achived that.

But the issue is, once a video automatically starts playing while scrolling, I navigate to another where I have a text input field. Once the keypad is opened for the text input the onViewableItemsChanged is being called which is in another screen and the video continues playing in the text input screen.

Below is the code of two different screens:

FlatListSample.js

import React, {useState, useCallback} from 'react';
import {StyleSheet, Text, View, FlatList, TouchableOpacity} from 'react-native';
import YouTubeIFrame from 'react-native-youtube-iframe';

const data = [
  {
    id: '60524193a4e2070001537f51',
    title: 'React Native Tutorial #1 - Introduction',
    videoLink: 'ur6I5m2nTvk',
  },
  {
    id: '6051f9bba4e2070001537f50',
    title: 'React Native Tutorial #2 - Creating a React Native App',
    videoLink: 'pflXnUNMsNk',
  },
  {
    id: '6051f98accf9d60001f80429',
    title: 'React Native Tutorial #3 - Views, Text & Styles',
    videoLink: '_YydVvnjNFE',
  },
  {
    id: '6051f94accf9d60001f80428',
    title: 'React Native Tutorial #4 - Using State',
    videoLink: '1FiIYaRr148',
  },
  {
    id: '6051f921ccf9d60001f80427',
    title: 'React Native Tutorial #5 - Text Inputs',
    videoLink: 'c9Sg9jDitm8',
  },
  {
    id: '6051f8e8ccf9d60001f80426',
    title: 'React Native Tutorial #6 - Lists & ScrollView',
    videoLink: 'W-pg1r6-T0g',
  },
  {
    id: '6051f897a4e2070001537f4f',
    title: 'React Native Tutorial #7 - Flat List Component',
    videoLink: 'iMCM1NceGJY',
  },
  {
    id: '6051f84ca4e2070001537f4e',
    title: 'React Native Tutorial #8 - Touchable Components',
    videoLink: 'QhX25YGf8qg',
  },
  {
    id: '6051f817ccf9d60001f80425',
    title: 'React Native Tutorial #9 - Todo App (part 1)',
    videoLink: 'uLHFPt9B2Os',
  },
  {
    id: '6051f7dba4e2070001537f4d',
    title: 'React Native Tutorial #10 - Todo App (part 2)',
    videoLink: 'SGEitne8N-Q',
  },
];

const FlatListSample = props => {
  const [visibleItemIndex, setVisibleItemIndex] = useState();
  const [viewabilityConfiguration, setViewabilityConfiguration] = useState({
    waitForInteraction: true,
    viewAreaCoveragePercentThreshold: 40,
  });

  const onViewableItemsChangedHandler = useCallback(
    ({viewableItems, changed}) => {
      console.log('Viewable item');
      if (viewableItems && viewableItems.length !== 0) {
        setVisibleItemIndex(viewableItems[0].index);
      }
    },
    [],
  );

  const renderItem = ({item, index}) => {
    return (
      <View key={item.id} style={styles.videoSec}>
        <Text style={styles.videoTitle}>{item.title}</Text>
        <TouchableOpacity
          activeOpacity={0.9}
          onPress={() => {
            setVisibleItemIndex(null);
            props.navigation.navigate('TextInputSample');
          }}>
          <YouTubeIFrame
            videoId={item.videoLink}
            height={230}
            play={index === visibleItemIndex}
            initialPlayerParams={{rel: false, controls: false, loop: true}}
          />
        </TouchableOpacity>
      </View>
    );
  };
  return (
    <View style={styles.container}>
      <FlatList
        style={{flex: 1}}
        data={data}
        renderItem={renderItem}
        keyExtractor={item => item.id}
        viewabilityConfig={viewabilityConfiguration}
        onViewableItemsChanged={onViewableItemsChangedHandler}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F7F7F7',
  },
  videoSec: {
    flex: 1,
    paddingVertical: 10,
    borderBottomColor: '#FCEABC',
    borderBottomWidth: 3,
    backgroundColor: '#FFFFFF',
  },
  videoTitle: {
    fontSize: 16,
    color: '#1B110A',
    paddingHorizontal: 10,
    marginBottom: 5,
  },
});

export default FlatListSample;

TextInputSample.js

import React from 'react';
import {View, TextInput} from 'react-native';

const TextInputSample = () => {
  return (
    <View>
      <TextInput
        style={{height: 40, backgroundColor: 'azure', fontSize: 20}}
        placeholder="Type here to translate!"
        onChangeText={text => console.log(text)}
      />
    </View>
  );
};

export default TextInputSample;

When I navigate from FlatListSample.js after some scroll to TextInputSample.js and open keypad the video starts playing again. Can someone please find a solution to this!

Thanking in advance for the solution.

I'm facing an issue with the onViewableItemsChanged prop from the flat-list. I have a list of videos that are being played when a single video es viewable on the screen, I achived that.

But the issue is, once a video automatically starts playing while scrolling, I navigate to another where I have a text input field. Once the keypad is opened for the text input the onViewableItemsChanged is being called which is in another screen and the video continues playing in the text input screen.

Below is the code of two different screens:

FlatListSample.js

import React, {useState, useCallback} from 'react';
import {StyleSheet, Text, View, FlatList, TouchableOpacity} from 'react-native';
import YouTubeIFrame from 'react-native-youtube-iframe';

const data = [
  {
    id: '60524193a4e2070001537f51',
    title: 'React Native Tutorial #1 - Introduction',
    videoLink: 'ur6I5m2nTvk',
  },
  {
    id: '6051f9bba4e2070001537f50',
    title: 'React Native Tutorial #2 - Creating a React Native App',
    videoLink: 'pflXnUNMsNk',
  },
  {
    id: '6051f98accf9d60001f80429',
    title: 'React Native Tutorial #3 - Views, Text & Styles',
    videoLink: '_YydVvnjNFE',
  },
  {
    id: '6051f94accf9d60001f80428',
    title: 'React Native Tutorial #4 - Using State',
    videoLink: '1FiIYaRr148',
  },
  {
    id: '6051f921ccf9d60001f80427',
    title: 'React Native Tutorial #5 - Text Inputs',
    videoLink: 'c9Sg9jDitm8',
  },
  {
    id: '6051f8e8ccf9d60001f80426',
    title: 'React Native Tutorial #6 - Lists & ScrollView',
    videoLink: 'W-pg1r6-T0g',
  },
  {
    id: '6051f897a4e2070001537f4f',
    title: 'React Native Tutorial #7 - Flat List Component',
    videoLink: 'iMCM1NceGJY',
  },
  {
    id: '6051f84ca4e2070001537f4e',
    title: 'React Native Tutorial #8 - Touchable Components',
    videoLink: 'QhX25YGf8qg',
  },
  {
    id: '6051f817ccf9d60001f80425',
    title: 'React Native Tutorial #9 - Todo App (part 1)',
    videoLink: 'uLHFPt9B2Os',
  },
  {
    id: '6051f7dba4e2070001537f4d',
    title: 'React Native Tutorial #10 - Todo App (part 2)',
    videoLink: 'SGEitne8N-Q',
  },
];

const FlatListSample = props => {
  const [visibleItemIndex, setVisibleItemIndex] = useState();
  const [viewabilityConfiguration, setViewabilityConfiguration] = useState({
    waitForInteraction: true,
    viewAreaCoveragePercentThreshold: 40,
  });

  const onViewableItemsChangedHandler = useCallback(
    ({viewableItems, changed}) => {
      console.log('Viewable item');
      if (viewableItems && viewableItems.length !== 0) {
        setVisibleItemIndex(viewableItems[0].index);
      }
    },
    [],
  );

  const renderItem = ({item, index}) => {
    return (
      <View key={item.id} style={styles.videoSec}>
        <Text style={styles.videoTitle}>{item.title}</Text>
        <TouchableOpacity
          activeOpacity={0.9}
          onPress={() => {
            setVisibleItemIndex(null);
            props.navigation.navigate('TextInputSample');
          }}>
          <YouTubeIFrame
            videoId={item.videoLink}
            height={230}
            play={index === visibleItemIndex}
            initialPlayerParams={{rel: false, controls: false, loop: true}}
          />
        </TouchableOpacity>
      </View>
    );
  };
  return (
    <View style={styles.container}>
      <FlatList
        style={{flex: 1}}
        data={data}
        renderItem={renderItem}
        keyExtractor={item => item.id}
        viewabilityConfig={viewabilityConfiguration}
        onViewableItemsChanged={onViewableItemsChangedHandler}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F7F7F7',
  },
  videoSec: {
    flex: 1,
    paddingVertical: 10,
    borderBottomColor: '#FCEABC',
    borderBottomWidth: 3,
    backgroundColor: '#FFFFFF',
  },
  videoTitle: {
    fontSize: 16,
    color: '#1B110A',
    paddingHorizontal: 10,
    marginBottom: 5,
  },
});

export default FlatListSample;

TextInputSample.js

import React from 'react';
import {View, TextInput} from 'react-native';

const TextInputSample = () => {
  return (
    <View>
      <TextInput
        style={{height: 40, backgroundColor: 'azure', fontSize: 20}}
        placeholder="Type here to translate!"
        onChangeText={text => console.log(text)}
      />
    </View>
  );
};

export default TextInputSample;

When I navigate from FlatListSample.js after some scroll to TextInputSample.js and open keypad the video starts playing again. Can someone please find a solution to this!

Thanking in advance for the solution.

Share asked Apr 5, 2021 at 16:25 VineelVineel 2652 gold badges4 silver badges12 bronze badges 1
  • let me check, i'll get back to you once i validate it. :) – Lakshman Kambam Commented Apr 6, 2021 at 6:35
Add a ment  | 

1 Answer 1

Reset to default 4

well, i just validated in both IOS and Android. It seems the issue is in android only. also it's weird behavior.

tried to find the cause of the problem by looking at react navigation screens stack, debugged a lot but couldn't track it yet.

in your case i have e up with 2 ways to solve your problem. (open for better solution)

  1. change focused boolean value with navigation eventListeners 'blur' and 'focus'
import React, {useState, useRef, useEffect} from 'react';
import { useCallback } from 'react';
import {StyleSheet, Text, View, FlatList, TouchableOpacity} from 'react-native';
import YouTubeIFrame from 'react-native-youtube-iframe'; 

const data = [
  {
    id: '60524193a4e2070001537f51',
    title: 'React Native Tutorial #1 - Introduction',
    videoLink: 'ur6I5m2nTvk',
  },
  {
    id: '6051f9bba4e2070001537f50',
    title: 'React Native Tutorial #2 - Creating a React Native App',
    videoLink: 'pflXnUNMsNk',
  },
  {
    id: '6051f98accf9d60001f80429',
    title: 'React Native Tutorial #3 - Views, Text & Styles',
    videoLink: '_YydVvnjNFE',
  },
  {
    id: '6051f94accf9d60001f80428',
    title: 'React Native Tutorial #4 - Using State',
    videoLink: '1FiIYaRr148',
  },
  {
    id: '6051f921ccf9d60001f80427',
    title: 'React Native Tutorial #5 - Text Inputs',
    videoLink: 'c9Sg9jDitm8',
  },
  {
    id: '6051f8e8ccf9d60001f80426',
    title: 'React Native Tutorial #6 - Lists & ScrollView',
    videoLink: 'W-pg1r6-T0g',
  },
  {
    id: '6051f897a4e2070001537f4f',
    title: 'React Native Tutorial #7 - Flat List Component',
    videoLink: 'iMCM1NceGJY',
  },
  {
    id: '6051f84ca4e2070001537f4e',
    title: 'React Native Tutorial #8 - Touchable Components',
    videoLink: 'QhX25YGf8qg',
  },
  {
    id: '6051f817ccf9d60001f80425',
    title: 'React Native Tutorial #9 - Todo App (part 1)',
    videoLink: 'uLHFPt9B2Os',
  },
  {
    id: '6051f7dba4e2070001537f4d',
    title: 'React Native Tutorial #10 - Todo App (part 2)',
    videoLink: 'SGEitne8N-Q',
  },
];

const FlatListExample = (props) => {

  const [visibleItemIndex, setVisibleItemIndex] = useState();
  const [focused, setFocused] = useState();

  const viewabilityConfig = {
    itemVisiblePercentThreshold: 40,
    waitForInteraction: true,
  };

  useEffect(() => {
    const subscribeFocusEvent = props.navigation.addListener('focus', () => {
      setFocused(true);
      console.log('focus', focused);
    });
    const subscribeBlurEvent = props.navigation.addListener('blur', () => {
      setFocused(false);
      console.log('blur', focused);
    });
    return (() => {
      subscribeFocusEvent;
      subscribeBlurEvent;
    });
  }, [focused]);
  
  
  const onViewableItemsChanged = useCallback(({ viewableItems, changed }) => {
    console.log({
      message: 'triggers change....1', 
      viewableItems, 
      changed,
      focused
    }, 'CHECK');
    if (changed && changed.length > 0) {
      setVisibleItemIndex(changed[0].index);
    }
  });

  const viewabilityConfigCallbackPairs = useRef([{ viewabilityConfig, onViewableItemsChanged }]);
  
  const renderItem = ({item, index}) => {
    return (
      <View key={item.id} style={styles.videoSec}>
        <Text style={styles.videoTitle}>{item.title}</Text>
        <TouchableOpacity
          activeOpacity={0.9}
          onPress={() => {
            setVisibleItemIndex(null);
            // props.navigation.navigate('Shop');
          }}>
          <YouTubeIFrame
            videoId={item.videoLink}
            height={230}
            play={index === visibleItemIndex}
            initialPlayerParams={{rel: false, controls: false, loop: true}}
          />
        </TouchableOpacity>
      </View>
    );
  };
  if(focused) {
    return (
      <View style={styles.container}>
        <FlatList
          style={{flex: 1}}
          data={data}
          renderItem={renderItem}
          keyExtractor={item => item.id}
          viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current}
        />
      </View>
    );
  }
  return null;
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F7F7F7',
  },
  videoSec: {
    flex: 1,
    paddingVertical: 10,
    borderBottomColor: '#FCEABC',
    borderBottomWidth: 3,
    backgroundColor: '#FFFFFF',
  },
  videoTitle: {
    fontSize: 16,
    color: '#1B110A',
    paddingHorizontal: 10,
    marginBottom: 5,
  },
});

export default FlatListExample;
  1. getCurrentRouteName of screen and render flatList. so that way it will render only if it's same screen.
export const FlatListScreen = ({ navigation, route }) => {

    console.log(route.name);

    // this screen title
    if(route.name === 'VideoScreen') {
        return (
            <FlatList 
                {...props}
            />
        );
    }
    return null;
};

let me know if you need any clarification any time.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745069333a4609449.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信