简体   繁体   中英

Basic react native question covert Class to Function

It might sound silly but I am just learning here I am trying to convert a component to a function-based component. I did everything right but I am stuck on something very silly

I have this code for Discover

export default class Discover extends React.PureComponent {
  state = {
    items: [],
  };
    cellRefs: {};

  constructor(props) {
    super(props);
    this.cellRefs = {};
  }

what is the correct way to convert cellRefs to work with the function I have? I tried everything when I do this in my class file it is fine it gives me an object with the things I need.

const cell = this.cellRefs[item.key];

However,

const cell = cellRefs[item.key];

is just giving undefined

Full code for the converted component

import React, { useState, useEffect, useRef, Children } from 'react';
import {
  StyleSheet,
  Text,
  View,
  FlatList,
  Dimensions,
  TouchableOpacity,
  Image,
} from 'react-native';
import { Video } from 'expo-av';




const { height, width } = Dimensions.get('window');

const cellHeight = height * 0.6;
const cellWidth = width;

const viewabilityConfig = {
itemVisiblePercentThreshold: 80,
};



class Item extends React.PureComponent {
  video: any;
  componentWillUnmount() {
    if (this.video) {
      this.video.unloadAsync();
    }
  }

  async play() {
    const status = await this.video.getStatusAsync();
    if (status.isPlaying) {
      return;
    }
    return this.video.playAsync();
  }

  pause() {
    if (this.video) {
      this.video.pauseAsync();
    }
  }

  render() {
    const { id, poster, url } = this.props;
    const uri = url + '?bust=' + id;
    return (
      <View style={styles.cell}>
        <Image
          source={{
            uri: poster,
            cache: 'force-cache',
          }}
          style={[styles.full, styles.poster]}
        />
        <Video
          ref={ref => {
            this.video = ref;
          }}
          source={{ uri }}
          shouldPlay={false}
          isMuted
          isLooping
          resizeMode="cover"
          style={styles.full}
        />
        <View style={styles.overlay}>
          <Text style={styles.overlayText}>Item no. {id}</Text>
          <Text style={styles.overlayText}>Overlay text here</Text>
        </View>
      </View>
    );
  }
}







interface FeedListProps {

}

export const FeedList: React.FC<FeedListProps> = (props) => {
  const initialItems = [
    {
      id: 1,
      url: 'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/IMG_1110.m4v',
      poster:
        'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/norwaysailing.jpg',
    },
    {
      id: 2,
      url:
        'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/croatia10s.mp4',
      poster:
        'https://s3.eu-west-2.amazonaws.com/jensun-uploads/shout/croatia10s.jpg',
    },
  ];
  const [items, setItems] = useState([]);
  //this.cellRefs = {};
  //let cellRefs: {};
  //cellRefs= {};
  const cellRefs = React.useRef({})
  const viewConfigRef = React.useRef({ itemVisiblePercentThreshold: 80 })
 

  useEffect(() => {
    loadItems();
    setTimeout(loadItems, 1000);
    setTimeout(loadItems, 1100);
    setTimeout(loadItems, 1200);
    setTimeout(loadItems, 1300);
  }, []);

  const _onViewableItemsChanged = React.useRef((props)=>{
    const changed = props.changed;
    changed.forEach(item => {
      const cell = cellRefs[item.key];
      
      console.log("CALLING IF"+ cell + "        " + item.key)
      if (cell) {
        if (item.isViewable) {
          console.log("PLAY OS CALLED")
          cell.play();
        } else {
          console.log("Pause is played")
          cell.pause();
        }
      }
    });
  });

  function loadItems(){

    const start = items.length;

    const newItems = initialItems.map((item, i) => ({
      ...item,
      id: start + i,
    }));

    const Litems = [...items, ...newItems];

    setItems( Litems );

  };

  function _renderItem({ item }){
    return (
      <Item
        ref={cellRefs[item.id]}
        {...item}
      />
    );
  };



    return (

      <View style={styles.container}>
        <FlatList
          style={{ flex: 1 }}
          data={items}
          renderItem={_renderItem}
          keyExtractor={item => item.id.toString()}
          onViewableItemsChanged={_onViewableItemsChanged.current}
          initialNumToRender={3}
          maxToRenderPerBatch={3}
          windowSize={5}
          getItemLayout={(_data, index) => ({
            length: cellHeight,
            offset: cellHeight * index,
            index,
          })}
          viewabilityConfig={viewabilityConfig}
          removeClippedSubviews={true}
          ListFooterComponent={
            <TouchableOpacity onPress={loadItems}>
              <Text style={{ padding: 30 }}>Load more</Text>
            </TouchableOpacity>
          }
        />
      </View>
    );
}



const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  cell: {
    width: cellWidth - 20,
    height: cellHeight - 20,
    backgroundColor: '#eee',
    borderRadius: 20,
    overflow: 'hidden',
    margin: 10,
  },
  overlay: {
    position: 'absolute',
    top: 0,
    right: 0,
    bottom: 0,
    left: 0,
    backgroundColor: 'rgba(0,0,0,0.4)',
    padding: 40,
  },
  full: {
    position: 'absolute',
    top: 0,
    right: 0,
    bottom: 0,
    left: 0,
  },
  poster: {
    resizeMode: 'cover',
  },
  overlayText: {
    color: '#fff',
  },
});

It would be best if you could inline your source code into stack overflow, than keeping it in a separate link. However I took a look at the component, and I think the issue is with how you are using props.

On line 91,

export const FeedList: React.FC<FeedListProps> = ({}) => {

So here, you need to get the props as an argument. Earlier with the class component it was available at this.props . However here you need to pass it as below,

export const FeedList: React.FC<FeedListProps> = (props) => {

Or you may destructure the props as below,

export const FeedList: React.FC<FeedListProps> = ({changed}) => {

You will also need to modify the interface on line 87 to reflect the type.

Should be enough to use a functional component and use useRef([]) initialized as an array

Working example: https://snack.expo.io/2_xrzF!LZ

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM