React Native Flatlist不要在PureComponent上重新呈现

时间:2018-07-18 07:41:27

标签: javascript reactjs react-native ecmascript-6

以下是我的平面列表代码。它工作正常,但有点滞后。因此,我在互联网上进行了一些搜索,发现将Component更改为PureComponent可以提高平板列表的性能。所以我改变了它,但是之后我的iconType不起作用。用户触摸列表项时,该复选框不会更改。 PureComponent不会在触摸时重新渲染吗?

<FlatList
  style={{flex:1}}
  data={finalData}
  showsVerticalScrollIndicator={false}
  renderItem={({item})=>{
    var iconType = (this.state.selectedItems.indexOf(item.name)>-1?"ios-checkmark-circle":"ios-checkmark-circle-outline");
    return(
      <TouchableOpacity
        onPress={
          ()=>{
            var selectedItems = this.state.selectedItems;
            var selectedItemsData = this.state.selectedItemsData;
            if(selectedItems.indexOf(item.name)>-1){
              const index = selectedItems.indexOf(item.name);
              selectedItems.splice(index, 1);
              selectedItemsData.splice(index,1);
            }else{
              selectedItems.push(item.name);
              selectedItemsData.push({name:item.name,id:item.id});
            }

            this.setState({selectedItems});
            this.setState({selectedItemsData});
          }}>
        <View style={{padding:20,flexDirection:'row',alignItems:'flex-start'}}>
          <Icon name={iconType} color="#45AA6F" size={25} />
          <Text style={{marginLeft:10,paddingTop:4,color:'#9B9B9B',fontWeight:'500'}}>{item.name}</Text>
        </View>
        <Dash style={{height:1}} dashColor="#45AA6F"/>
      </TouchableOpacity>)}
  }
/>

2 个答案:

答案 0 :(得分:1)

PureComponent将防止浪费的重新渲染,除非实际的ID发生更改, 通过将 extraData = {this.state} 传递给FlatList,我们可以确保在state.selected更改时FlatList本身将重新呈现。只需将extraData属性添加到您的列表组件即可。来源:Official Document Flatlist

 /* Sample FlatList Example */

import React, { PureComponent} from 'react';
import {
  FlatList,
  StyleSheet,
  Switch,
  Text,
  View,
} from 'react-native';

export default class FlatListView extends PureComponent {
 
  constructor(props: Object) {
    super(props);
    this.state = {
      words: [
        { key: 1, text: 'Notification', toggle:false}, 
        { key: 2, text: 'Wifi', toggle:false}, 
        { key: 3, text: 'Bluetooth', toggle:false}
      ]
    }
  };

  render() {
    return( 
      <FlatList
        data={this.state.words}
        extraData={this.state}
        renderItem={({item, index}) => 
          <View style={styles.wordsContainer}>
            <Text>{item.text}</Text>
            <Switch
              style={styles.pilgrimsWordSwitch}
              onValueChange={(toggleValue) => {
             /*
              *  Cloning the words array to temp, So that the reference to this.state.words array will change.
              *  Means this.state.words === temp will give false value.
              */

                let temp = this.state.words.slice(0);
                temp[index].toggle = toggleValue;
                this.setState({words: temp});
              }}
              value={ item.toggle }
            />
          </View>
        }
      />
    )
  }
}

const styles = StyleSheet.create({
  wordsContainer: {
    alignItems:'center', 
    backgroundColor:'green',  
    flexDirection:'row',
    height:100, 
    justifyContent:'center', 
    padding:20,
  },
  pilgrimsWordSwitch: {
    flex:1, 
    justifyContent:'flex-end'
  }
});

答案 1 :(得分:-1)

不要改变数组,这可能导致组件无法重新渲染:

selectedItems.splice(index, 1); 替换为非变异过程。

您可能可以使用Array.filter https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Array.map https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

在这里您可以比较非变异和变异方法: https://lorenstewart.me/2017/01/22/javascript-array-methods-mutating-vs-non-mutating/