首页 > 解决方案 > ReactNative 与 Mobx - Flatlist 无限请求项目

问题描述

我的 ReactNative 环境如下:

React Native Environment Info:
System:
  OS: macOS 10.14
  CPU: x64 Intel(R) Core(TM) i7-7567U CPU @ 3.50GHz
  Memory: 37.92 MB / 16.00 GB
  Shell: 3.2.57 - /bin/bash
Binaries:
  Node: 8.12.0 - /usr/local/bin/node
  Yarn: 1.9.4 - /usr/local/bin/yarn
  npm: 6.4.1 - /usr/local/bin/npm
  Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
  iOS SDK:
    Platforms: iOS 11.2, macOS 10.13, tvOS 11.2, watchOS 4.2
IDEs:
  Android Studio: 3.1 AI-173.4907809
  Xcode: 9.2/9C40b - /usr/bin/xcodebuild
npmPackages:
  react: 16.5.2 => 16.5.2 
  react-native: 0.57.1 => 0.57.1 
npmGlobalPackages:
  create-react-native-app: 1.0.0
  react-native-cli: 2.0.1
  react-native-git-upgrade: 0.2.7

考虑以下类(2):

ItemStore.js

    import {action, computed, flow, observable} from "mobx";

class ItemStore {

    currentPage = 0;

    @observable loadingItems = false;
    @observable currentSearch = "";
    @observable items = [];

    @computed get emptyListText() {
        if (this.currentSearch.length === 0) {
            return "Busque Ahora!"
        } else if (this.loadingItems === true) {
            return "Buscando..."
        }
        return `No encontramos ningun resultado para "${this.currentSearch}"`
    }

    @action search(searchQuery) {
        this.currentSearch = searchQuery;
        this.loadItems(searchQuery, (this.currentPage = 0))
    }

    @action loadNextPage() {
        this.loadItems(this.currentSearch, (++this.currentPage))
    }

    @action loadItems = flow(function* (searchQuery, page) {
        try {
            this.loadingItems = true;
            const searchResults = yield fetch(`http://192.168.0.88:10000/search?keywords=${searchQuery}&page=${page}`, {
                method: 'GET',
                header: {
                    Accept: 'application/json',
                }
            });
            const data = yield searchResults.json();
            if (data.length > 0) {
                if (page === 0) { // brand new search, replace old items
                    this.items.replace(data)
                } else { // loading another page
                    this.items.push(...data)
                }
            }
        } catch (error) {
            console.warn(error);
        }
        this.loadingItems = false;
    });

 }
 export default new ItemStore();

ItemSearchScreen.js

    import React from 'react'
import {Body, Container, Content, Header, Icon, Input, Item, Text} from 'native-base'
import {inject, observer} from "mobx-react";
import {FlatList} from 'react-native'
import Product from "./Product";

@inject('itemStore')
@observer
export default class ItemSearchScreen extends React.Component {

    handleSearch = (e) => this.props.itemStore.search(e.nativeEvent.text);

    handleLoadNextPage = () => this.props.itemStore.loadNextPage();

    render() {
        const items = this.props.itemStore.items.slice();

        return (
            <Container>
                <Header searchBar rounded>
                    <Item>
                        <Icon name="ios-search"/>
                        <Input placeholder={"Buscar"}
                               onSubmitEditing={this.handleSearch}/>
                    </Item>
                </Header>
                <Content>
                    <FlatList
                        initialNumToRender={6}
                        ListEmptyComponent={
                            <Body>
                            <Text>{this.props.itemStore.emptyListText}</Text>
                            </Body>
                        }
                        data={items}
                        keyExtractor={(item) => item['id']}
                        onEndReached={this.handleLoadNextPage}
                        onEndReachedThreshold={0.5}
                        renderItem={({item}) => <Product product={item}/>}/>
                </Content>
            </Container>
        );
    };

}

目标是在 Flatlist 中获取并显示一组 json“产品”项目。

    import React from 'react'
import {observer} from "mobx-react";
import {Body, Left, ListItem, Text, Thumbnail} from 'native-base'

@observer
export default class Product extends React.Component {

    //should be replaced with cached app image
    fallBackImage = 'https://www.wpclipart.com/office/sale_promo/new_item/new_item_light_red.png';

    constructor(props) {
        super(props);
    }

    render() {
        let thumbnailImage = this.props.product['product_image_url'].length > 0 ? this.props.product['product_image_url'] : this.fallBackImage
        return (
            <ListItem>
                <Left>
                    <Thumbnail square large source={{uri: thumbnailImage}}/>
                    <Text>${this.props.product['price']}</Text>
                </Left>
                <Body>
                <Text>{this.props.product['name']}</Text>
                </Body>
            </ListItem>
        );
    }

}

通过搜索栏(在标题中)搜索产品时,会显示产品列表,但 Flatlist 会触发无限的 'onEndReached' => 'loadNextPage()' 调用。这会导致列表被无限填充(第 1、2、3.... 90、91... 页)。我相信这个问题可能是由于我使用 mobx 可观察数组和 Flatlist 是 PureComponent 造成的。但经过几个小时后,我似乎无法让它工作。

标签: javascriptreact-nativemobxmobx-react

解决方案


您可能已经尝试过,但可以在输入数据时尝试将可观察数组转换为数组

@observable myArray = []

data={[...myArray]}


推荐阅读