Невероятно плохая производительность с использованием компонентов высшего порядка, Redux и FlatList - PullRequest
0 голосов
/ 17 июня 2019

Моя проблема

https://imgur.com/fHHqSqF

Обратите внимание, что когда появляется список, я сразу нажимаю на первый элемент, но рендеринг занимает 5 секунд ... У меня та же проблемакогда я удаляю элемент из списка: https://imgur.com/1ChZYBy.

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

Что яуже попробовал:

  • Устанавливая реагирующий нативный отладчик, я не смог найти ничего плохого в своем редуксе, но я подозреваю тот факт, что когда я удаляю элемент из моего списка, я делаю array.filter вдля того, чтобы мой новый магазин был представлен в redux, который, кажется, не самый лучший для производительности
  • console.log, чтобы видеть каждый раз, когда компонент рендерит
  • Transformmed TripCell и typedTripList из классов вфункциональные компоненты
  • Пытался поставить shouldComponentUpdate() { return false } почти везде, где мог

Что я подозреваю

  • Я подозреваю TripCell, чтобы сделать рендеринг много раз
  • Может быть, я должен реализовать Redux Logic, а не into мой HOC, но прямо в моем TripList?
  • Я могу попытаться также преобразовать свой список, чтобы он стал функциональным компонентом
  • Может быть, список должен быть разрешен для получения данных из API, яследует ли разрешить эту задачу моему HOC?

Архитектура моего кода

TripListAllScreen - это экран, который показывает все поездки

TripListDriverScreen - это экранкоторый показывает все поездки, в которых пользователь является драйвером

enter image description here

Некоторые журналы при записи видео

enter image description here

Должно быть макс. 62 рендера, потому что здесь LIST_ALL содержит то же самое, что и LIST_DRIVER, и у меня всего 26 поездок.

Мой код

TripListAllScreen

export default class TripListAllScreen extends Component {
    render() {
        console.log(`RENDER : ${this.constructor.name}`);
        return (
            <View style={[{ flex: 1 }]}>
                <TripList listType={LISTE_ALL} />
            </View>
        );
    }
}

typedTripList

function typedTripList(WrappedTripList) {
    return function TypedTripList(props) {
        const {
            listType, dataList, setDataList, setSelectedTrip, setSelectedGeneralTrip, token,
        } = props;
        let route;
        switch (listType) {
        case LISTE_ALL:
            route = '/trip/get';
            break;
        case LIST_DRIVER:
            route = '/trip/getWhereUserIsDriver';
            break;
        default:
            route = '/trip/get';
        }

        console.log(`typedTripList.${props.listType}`);

        return (
            <WrappedTripList
                route={route}
                dataList={dataList}
                setDataList={setDataList}
                setSelectedTrip={setSelectedTrip}
                setSelectedGeneralTrip={setSelectedGeneralTrip}
                token={token}
            />
        );
    };
}

const mapStateToProps = (state, ownProps) => ({
    // Determine the redux dataList to use <all trips | where user is driver | where user is passenger>
    dataList: state.datalist[ownProps.listType],
    token: state.token.token,
});

const mapDispatchToProps = (dispatch, ownProps) => ({
    // Determine the redux dataList to use in set data list action
    // <all trips | where user is driver | where user is passenger>
    setDataList: data => dispatch(setDataListAction(data, ownProps.listType)),
    setSelectedTrip: idRecurrence => dispatch(setSelectedTripAction(idRecurrence)),
    setSelectedGeneralTrip: idTrajet => dispatch(setSelectedGeneralTripAction(idTrajet)),
});

typedTripList.propTypes = {
    listType: PropTypes.string.isRequired,
};

// Fixed the problem ! :)
const composedHoc = compose(
    connect(mapStateToProps, mapDispatchToProps),
    typedTripList,
);

export default composedHoc;

TripList.js

class TripList extends Component {
    state = {
        isReady: false,
        refreshing: false,
    }

    constructor(props) {
        super(props);
        this._getTrips();
    }

    // Trips should be got in typedTripList (OR MAYBE NOT: THEN DIFFICULT TO MANAGE LOADING)
    _getTrips = () => {
        const { token, setDataList, route } = this.props;
        // console.log('GETTING TRIPS');
        // console.log(`TOKEN: ${token}`);
        protectedGetRequest(route, token) // '/trip/get'
            .then(response => response.json())
            .then((json) => {
                this.setState({ isReady: true });
                setDataList(json.data);
            })
            .then(() => {
                this.setState({ refreshing: false });
            })
            .catch(e => console.log(e));
    }

    _renderTripCell = ({ item }) => (
        <TouchableOpacity onPress={() => this._navToTripDetails(item.idRecurrence, item.Trajet.idTrajet)}>
            <TripCell
                start={item.Trajet.EtapeTrajets[0].Etape.Nom}
                arrival={item.Trajet.EtapeTrajets[item.Trajet.EtapeTrajets.length - 1].Etape.Nom}
                datetime={this._renderDatetime(item)}
                seats={item.Trajet.NbPlaces}
                passengers={item.NbPassagers}
            />
        </TouchableOpacity>

    );

    _renderDatetime = (item) => {
        const date = mysqlToJsDate(item.Date);
        const dateTime = mysqlToJsDateTime(item.Trajet.HeureDepart);
        return {
            ...date,
            hours: dateTime.hours,
            minutes: dateTime.minutes,
        };
    }

    _navToTripDetails = (idRecurrence, idTrajet) => {
        const { navigation, setSelectedTrip, setSelectedGeneralTrip } = this.props;
        const { navigate } = navigation;

        // TODO: merge those functions
        setSelectedTrip(idRecurrence);
        setSelectedGeneralTrip(idTrajet);
        navigate('TripDetails');
    }

    render() {
        console.log(`RENDER : ${this.constructor.name}`);
        const { isReady, refreshing } = this.state;
        const { dataList } = this.props;

        if (!isReady) return (<Loading />);
        return (
            <View style={[styles.container]}>
                <FlatList
                    data={dataList}
                    keyExtractor={(item, index) => `${item.idRecurrence}-${index}`}
                    renderItem={this._renderTripCell}
                    refreshControl={(
                        <RefreshControl
                            refreshing={refreshing}
                            onRefresh={() => { this._getTrips(); }}
                        />
                    )}
                />
            </View>
        );
    }
}

export default typedTripList(withNavigation(TripList));

РЕДАКТИРОВАТЬ

Моя избыточная логика для удаления элементов из списков

case DELETE_ITEM:
        console.log('in delete item');
        return {
            ...state,
            [LISTE_ALL]: state[LISTE_ALL].filter(item => item.idRecurrence != action.payload.idRecurrence),
            [LIST_DRIVER]: state[LIST_DRIVER].filter(item => item.idRecurrence != action.payload.idRecurrence),
            [LIST_PASSENGER]: state[LIST_PASSENGER].filter(item => item.idRecurrence != action.payload.idRecurrence),
        };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...