Почему перехватчики реакции не поддерживают purecomponent или функцию shouldComponentUpdate? - PullRequest
0 голосов
/ 17 июня 2020

Я хочу реализовать функцию множественного выбора плоского списка. Я прямо на официальном сайте поменял пример. Официальный адрес сайта: https: /reactnative.cn/docs/flatlist. Поскольку в списке много элементов, я хочу использовать shouldComponentUpdate, чтобы предотвратить чрезмерное отображение элементов. Но я обнаружил, что метод записи перехватчиков не может обеспечить множественный выбор, он не может сохранить выбранное состояние, но метод записи класса может обеспечить множественный выбор, в чем причина? Исходный код FlatList Item выглядит следующим образом:

    import {StyleSheet, Text, TouchableOpacity} from 'react-native';
import React, {Component} from 'react';

class Item extends Component {
    shouldComponentUpdate(nextProps, nextState) {
        return this.props.selected !== nextProps.selected;

    }

    render() {
        const {title, onSelect, selected, id} = this.props;
        console.log(title + ' is render');
        return (
            <TouchableOpacity
                onPress={() => onSelect(id)}
                style={[
                    styles.item,
                    {backgroundColor: selected ? '#6e3b6e' : '#f9c2ff'},
                ]}
            >
                <Text style={styles.title}>{title}</Text>
            </TouchableOpacity>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 40,
    },
    item: {
        backgroundColor: '#f9c2ff',
        padding: 20,
        marginVertical: 8,
        marginHorizontal: 16,
    },
    title: {
        fontSize: 32,
    },
});
export default Item;

Исходный код приложения для записи класса выглядит следующим образом:

    import React, {Component} from 'react';
import {
    View,
    FlatList,
    StyleSheet,
} from 'react-native';
import Item from '../component/Item';

const DATA = [
    {
        id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
        title: 'First Item',
    },
    {
        id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
        title: 'Second Item',
    },
    {
        id: '58694a0f-3da1-471f-bd96-145571e29d72',
        title: 'Third Item',
    },
];

class App extends Component {
    state = {
        selected: new Map(),
    };
    onSelect = (id) => {
        const newSelected = new Map(this.state.selected);
        newSelected.set(id, !this.state.selected.get(id));
        this.setState({
            selected: newSelected,
        });
    };

    renderItem = ({item}) => (
        <Item
            id={item.id}
            title={item.title}
            selected={this.state.selected.get(item.id)}
            onSelect={this.onSelect}
        />
    );

    render() {
        return (
            <View style={styles.container}>
                <FlatList
                    data={DATA}
                    renderItem={this.renderItem}
                    keyExtractor={item => item.id}
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 40,
    },
    item: {
        backgroundColor: '#f9c2ff',
        padding: 20,
        marginVertical: 8,
        marginHorizontal: 16,
    },
    title: {
        fontSize: 32,
    },
});

export default App;

Исходный код хуков приложения выглядит следующим образом.

 import React, {Component, useState} from 'react';
import {
    View,
    FlatList,
    StyleSheet,
} from 'react-native';
import Item from '../component/Item';

const DATA = [
    {
        id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
        title: 'First Item',
    },
    {
        id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
        title: 'Second Item',
    },
    {
        id: '58694a0f-3da1-471f-bd96-145571e29d72',
        title: 'Third Item',
    },
];
const App = () => {
    const [selected, setSelected] = useState(new Map());
    const onSelect = (id) => {
        const newSelected = new Map(selected);
        newSelected.set(id, !selected.get(id));
        setSelected(newSelected);
    };

    const renderItem = ({item}) => (
        <Item
            id={item.id}
            title={item.title}
            selected={selected.get(item.id)}
            onSelect={onSelect}
        />
    );
    return (
        <View style={styles.container}>
            <FlatList
                data={DATA}
                renderItem={renderItem}
                keyExtractor={item => item.id}
            />
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 40,
    },
    item: {
        backgroundColor: '#f9c2ff',
        padding: 20,
        marginVertical: 8,
        marginHorizontal: 16,
    },
    title: {
        fontSize: 32,
    },
});

export default App;

Ответы [ 2 ]

0 голосов
/ 17 июня 2020

Прочтите о VritualizedList , который расширяет FlatList

Внутреннее состояние не сохраняется при прокрутке содержимого за пределы окна рендеринга. Убедитесь, что все ваши данные сохранены в данных элемента или во внешних хранилищах, таких как Flux, Redux или Relay.

Короче говоря, попытки оптимизировать элементы FlatList с помощью shouldComponentUpdate или React.memo в большинстве случаев бессмысленны - items не сохраняют свое состояние и перемонтируются на рендере. Даже если бы вы использовали компоненты класса с shouldComponentUpdate, это не помогло бы, поскольку при каждом рендеринге ваши компоненты уничтожаются и создаются заново. FlatList уже оптимизирует для вас производительность, отображая только ограниченное количество элементов вместо одновременного отображения всего списка

0 голосов
/ 17 июня 2020

React.memo предназначен для shouldComponentUpdate. Вот официальный do c: https://reactjs.org/docs/hooks-faq.html#how -do-i-implementation-shouldcomponentupdate

...