【问题标题】:React Native avoid FlatList re-render when I select one item当我选择一项时,React Native 避免 FlatList 重新渲染
【发布时间】:2020-11-16 06:49:28
【问题描述】:

说明

我正在实现一个图像选择器,但有一些我需要解决的性能问题... 在我的组件中,用户可以从他的画廊中选择多个项目(图像)(FlatList 呈现他画廊中的所有图像)。当某个项目被选中时,它被添加到所选图像的数组中(它是一个状态)。

问题

由于数组是有状态的,组件将重新渲染...但我只需要重新渲染用户单击的图像(因为其中会显示一个徽章)而不是完整的 FlatList。

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

代码

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 包装器

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 2018-12-27
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 2018-06-20
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多