当我选择一项时,React Native避免FlatList重新呈现

时间:2020-07-26 23:31:10

标签: javascript reactjs react-native ecmascript-6 expo

说明

我正在实现图像选择器,但是有一些性能问题需要解决... 在我的组件中,用户可以从其图库中选择多个项目(图像)(FlatList呈现其图库中的所有图像)。选择某些项目后,会将其添加到所选图像阵列中(这是一种状态)。

问题

由于数组是有状态的,组件将重新呈现...但是我只需要重新呈现用户单击的图像(因为它将在其中显示徽章),而不是完整的FlatList。 / p>

任何想法如何做到这一点?

CODE

const keyExtractor = ({ uri }) => uri;

class ImagePicker extends React.Component {
  static propTypes = {
    ...
  };

  loading = false;
  cursor = null;

  state = {
    images: [],
    pickedImages: [], // <----------------------------------
  };

  componentDidMount() {
    this.getImages();
  }

  getImages = async (after) => {
    if (this.loading) return;

    this.loading = true;

    const results = await MediaLibrary.getAssetsAsync({
      first: 20,
      after,
      sortBy: MediaLibrary.SortBy.creationTime,
    });

    const { assets, hasNextPage, endCursor } = results;

    this.setState({ images: this.state.images.concat(assets) }, () => {
      this.loading = false;
      this.cursor = hasNextPage ? endCursor : null;
    });
  };

  getNextImages = () => {
    // If there are no more pics to get, do nothing
    if (!this.cursor) return;

    /*
      If we don't check the above condition,
      once we reach the final of the camera roll,
      the beginning will be loaded again
    */

    this.getImages(this.cursor);
  };

  pickImage = (image) => {
    /*
      This method returns a boolean that indicates 
      if it was possible to select the image tapped by the user 
    */
    const { pickedImages } = this.state;

    // If the element is already in the list remove it
    if (isElementInList(image, pickedImages)) {
      this.setState({
        pickedImages: removeListElement(image, pickedImages),
      });

      return false;
    }

    // Do nothing if the user has already selected MAX_ALBUM_LENGTH images
    if (pickedImages.length === MAX_ALBUM_LENGTH) return false;

    // If the image is not currently picked, add it to the list of picked images
    if (!isElementInList(image, pickedImages)) {
      this.setState({
        pickedImages: [...pickedImages, image], // <----------------------------------------
      });

      return true;
    }
  };

  renderItem = ({ item: { uri }, size, marginTop, marginLeft }) => {
    const style = {
      width: size,
      height: size,
      marginLeft,
      marginTop,
    };

    const { pickedImages } = this.state;

    return (
      <Item
        uri={uri}
        onPress={this.pickImage}
        pickedImages={pickedImages}
        style={style}
      />
    );
  };

  render() {
    const {
      theme: { colors },
      handleClose,
      handleConfirm,
    } = this.props;

    const { images, pickedImages } = this.state;

    return (
      <>
        <View style={styles.topButtonsContainer}>
          <TouchableOpacity
            activeOpacity={0.5}
            style={styles.topButton}
            onPress={handleClose}
          >
            <Icon
              name="ios-close"
              type="ionicon"
              color={colors.black}
              size={40}
            />
          </TouchableOpacity>
          {pickedImages.length > 0 && (
            <TouchableOpacity
              activeOpacity={0.5}
              style={styles.topButton}
              onPress={handleConfirm}
            >
              <Icon
                name="ios-checkmark"
                type="ionicon"
                color={colors.black}
                size={40}
              />
            </TouchableOpacity>
          )}
        </View>
        <Grid
          data={images}
          keyExtractor={keyExtractor}
          renderItem={this.renderItem}
          initialNumToRender={20}
          removeClippedSubviews
          onEndReached={this.getNextImages}
        />
      </>
    );
  }
}

Pd:组件“ Grid”只是一个FlatList包装器

1 个答案:

答案 0 :(得分:0)

我唯一要做的就是将项目从PureComponent移到Component并按如下所示修改shouldComponentUpdate:

shouldComponentUpdate(nextProps, nextState) {
  // If the state "isSelected" has changed then update
  return nextState.isSelected !== this.state.isSelected;
}