使用高阶组件,Redux和FlatList的性能令人难以置信

时间:2019-06-17 15:54:03

标签: reactjs react-native redux react-redux

我的问题

https://imgur.com/fHHqSqF

请注意,当列表出现时,我直接单击了第一项,但是渲染需要5秒钟...从列表中删除项目时,我遇到了同样的问题:https://imgur.com/1ChZYBy

退出调试模式时,列表出现时响应速度更快,但是删除项目时响应速度仍然很慢。

我已经尝试过的:

  • 安装react native调试器后,我的redux找不到任何问题,但是我怀疑这样一个事实,当我删除列表中的某个项目时,我执行了array.filter以便从redux中获得新存储,这似乎不是表演的最佳选择
  • console.log,每次组件渲染时查看
  • TripCelltypedTripList从类转换为功能组件
  • 试图将shouldComponentUpdate() { return false }放在几乎我可以使用的任何地方

我怀疑

  • 我怀疑TripCell渲染了很多次
  • 也许我应该将Redux Logic而不是直接在我的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));

编辑

我的redux逻辑,用于从列表中删除项目

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),
        };

0 个答案:

没有答案