经过一些研究,似乎我需要使用PureComponent而不是常规Component来提高FlatList的速度。这样,它将不会仅呈现已更改的行,而是仅重新呈现整个列表。但是,当我以这种方式进行操作时,统一列表不会重新呈现。

这个问题How to re-render flatlist?和其他类似的问题指出,我必须在我的extradata={this.state}中使用FlatList,以便可以查看数据源中是否发生了任何数据更改,但是它不起作用

我尝试过this.state,this.state.symbols,尝试使用布尔值并在onPress函数中强制更改它,但似乎没有任何效果。

我将列表项从render函数移到了外部js文件中的自己的类中

export default class MyListItem extends React.PureComponent {
    render() {
        const { item } = this.props;
        return (
            <View style={{flex: 1, flexDirection: 'row'}}>
                <View style={{backgroundColor: 'powderblue'}}>
                    <Ionicons style={styles.listItemIcon} name={item.iconName} />
                </View>
                <View style={{backgroundColor: 'skyblue'}}>
                    <Text style={styles.listItem}>
                        {item.coinName.toUpperCase()} {item.symbol}
                    </Text>
                </View>
            </View>
        );
    };
}


我的renderListItem函数现在看起来像这样

renderListItem = ({ item , index}) => {
        return(
            <TouchableOpacity
                onPress={() => this.onPressListItem(index)}
            >
            <MyListItem
            item={item}
            />
            </TouchableOpacity>
        )
    }


这是onPress函数。如您所见,这里的状态已更改,所以不确定为什么extraData看不到

onPressListItem = ( index ) => {
        const copyOfSymbolsList = [...this.state.symbols];
        thePressedSymbol = copyOfSymbolsList[index];

        if (thePressedSymbol.iconName === 'md-star') {
            thePressedSymbol.iconName = 'md-star-outline';
        }else{
            thePressedSymbol.iconName = 'md-star';
        }
        copyOfSymbolsList[index] = thePressedSymbol;

        this.setState({
            symbols: copyOfSymbolsList
        });

    }


这是我的平面清单

<FlatList
                    data={this.state.symbols}
                    extraData={this.state.symbols}
                    keyExtractor= {(item, index) => item.symbol}
                    ItemSeparatorComponent={this.renderListSeparator}
                    renderItem={this.renderListItem}
                />

最佳答案

您可能需要像这样在thePressedSymbol函数中操纵onPressListItem



onPressListItem = ( index ) => {
        const copyOfSymbolsList = [...this.state.symbols];
        thePressedSymbol = {
          ...copyOfSymbolsList[index],
          iconName: copyOfSymbolsList[index].iconName === 'md-star' ? 'md-star-outline' : 'md-star';
        }
        copyOfSymbolsList[index] = thePressedSymbol;

        this.setState({
            symbols: copyOfSymbolsList
        });

    }


这是因为在Javascript中,对象是reference类型。您可以在控制台中尝试

var person1={
  name: 'John',
  age: 10
}
var person2 = person1;
console.log(person1===person2); // output: true
person2.age = 20;
console.log(person1===person2); // output: true
console.log(person1.age, person2.age); // output: 20 20

var person3 = {...person1};
console.log(person1===person3}; // output: false


这意味着,为了重新渲染FlatList,您需要传递一个全新的symbol项来替换数组中的现有项(这是我上面的解决方案所做的事情);或者(我还没有尝试过),您也可以实现自己的FlatList组件进行深度比较,而不是深度比较。

关于javascript - 即使使用extraData = {this.state},PureComponent FlatList也不会重新呈现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55448762/

10-15 14:31