加载 React Native 后呈现 RSS 提要数据

Rendering RSS Feed Data after Load React Native

我似乎在我的代码中缓慢加载数据时绊倒了,这阻止了我映射的自定义组件在渲染帧之前渲染 - 在相当长的时间内留下白色 space。我只是获取 rss 提要数据,对其进行解析,然后根据其 json 内容制作自定义组件。这是我的代码:

module.exports = React.createClass({
    /*
    mixins : [
        Reflux.listenTo(FeedStore, 'onChange')
    ],
    */
    componentWillMount: function() {
        Parse.User.currentAsync()
            .then((user) => { this.setState({user: user}); })

        //get the latest articles on page load
        //this will pre-fill out articles state 
        FeedStore.getArticles()
            .then((data) => {
                this.setState({ articles: data });
            });
    }, 
    getInitialState: function() {
        return {
            user: null, 
            username: null, 
            articles: [], 
        }
    },
    render: function() {

        var readings = this.state.articles; 

        return (
            <ScrollView>
                <ArticleView
                    category={'Comedy'}
                    key={1}
                    heartText={'2.9k'}
                    categoryPress={this.dummy}
                    selected={false}
                    source={require('../img/test_view_1.png')}
                    text={'These 3 black comedians are finally being honored for the ways they paved & the history they made'}
                    onPress={this.dummy} />
                <ArticleView
                    category={'City Life'}
                    key={2}
                    heartText={'299'}
                    categoryPress={this.dummy}
                    selected={false}
                    source={require('../img/test_view_2.png')}
                    text={'portland forecast: approaching weekend storm could rival halloween deluge'}
                    onPress={this.dummy} />
                <ArticleView
                    category={'Music'}
                    key={3}
                    heartText={'250k'}
                    categoryPress={this.dummy}
                    selected={false}
                    source={require('../img/test_view_3.png')}
                    text={'kendrick lamar answers furgeson criticism with new song'}
                    onPress={this.dummy} />
                {this.renderArticleFeed(readings)}
            </ScrollView>
        );
    }, 
    renderArticleFeed: function(readings) {
        var that = this;
        //call to api to get articles from rss/api var Articles = 
        return readings.slice(0,4).map(function(article, i) {
            console.log("========================");
            console.log(article.title);
            console.log(article.mediaGroups[0].contents[0].thumbnails[0].url);

            return <ArticleView
                    category={'Music'}
                    key={i}
                    heartText={'2.9k'}
                    categoryPress={that.dummy}
                    selected={false}
                    source={{uri: article.mediaGroups[0].contents[0].thumbnails[0].url }}
                    text={article.title}
                    onPress={that.dummy} />
        });

    }, 
    dummy: function() {

    }, 
    /*
    onChange: function(event, articles) {
        this.setState({articles: articles}); //trigers re-render of component
    }
    */

});

我很想深入研究有助于加载数据然后呈现结果的方法——而不是在数据实际及时格式化之前立即呈现。特别是切片 readings.slice(0,4).map(function(article, i).. 函数应该处理超过 4 个 rss 提要的案例 - 我需要它能够处理所有这些,或者至少在我向下滚动时,所有部分都是这样。

我确定了一个非常有效(而且很酷)的答案!持久化来自 api 调用的数据的方法是使用 ListView, which Facebook has ok information on. A better example of it's use is documented here. Check out the associated github repo here,这在连接概念点时非常有帮助,了解它是如何工作的,所以我不会详细介绍。

这是我的新(工作代码):

var React = require('react-native');
var {
    View, 
    Image,
    StyleSheet,
    Text, 
    ScrollView, 
    ActivityIndicatorIOS, 
    ListView, 
} = React;

//additional libraries
var Parse = require('parse/react-native');
//var Reflux = require('reflux');

//dynamic component references
var ArticleView = require('./article-view/article-view');
var Api = require('../utils/api');
var FeedStore = require('../stores/feed-store');
//var Actions = require('../../actions');

//dimensions
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');

module.exports = React.createClass({ 
    componentWillMount: function() {
        Parse.User.currentAsync()
            .then((user) => { this.setState({user: user}); })
    },  
    getInitialState: function() {

        var getSectionData = (dataBlob, sectionID) => {
            console.log("SectionID GIS, getSectionData: " + sectionID);
            return dataBlob[sectionID];
        }

        var getRowData = (dataBlob, sectionID, rowID) => {
            console.log("RowID GIS, getRowData: " + rowID);
            return dataBlob[sectionID + ':' + rowID];
        }

        return {
            user: null, 
            isLoaded: false, 
            dataSource : new ListView.DataSource({
                getSectionData          : getSectionData,
                getRowData              : getRowData,
                rowHasChanged           : (row1, row2) => row1 !== row2,
                sectionHeaderHasChanged : (s1, s2) => s1 !== s2
            })
        }
    },
    componentDidMount: function() {
        this.organizeData(); 
    },
    organizeData: function() {
        var data_store = null; 
        //get the latest articles on page load
        //this will pre-fill out articles state 
        FeedStore.getArticles()
            .then((data) => {
                console.log("================");
                console.log("data is at home");
                console.log(data);
                console.log("================");

                var entries = data, 
                length = entries.length,
                dataBlob = {},
                sectionIDs = [],
                rowIDs = [],
                entry,
                sectionID, 
                rowID, 
                i; 
                console.log(entries.length);
                for (i = 0; i < length; i++)
                {
                    entry = entries[i]; 
                    console.log(entry);

                    //add section/row to section id array

                    //mapping section id array for section data 
                    sectionID = entry.title.replace(/\s+/g, '').toLowerCase() + i; 
                    console.log("SectionID = " + sectionID);
                    sectionIDs.push(sectionID);
                    dataBlob[sectionID] = entry.title; 

                    //mapping row id array for row data 
                    rowIDs[i] = []
                    rowID = sectionID;
                    console.log("RowID = " + rowID);
                    rowIDs[i].push(rowID);
                    dataBlob[sectionID + ':' + rowID] = entry; 
                }

                console.log(dataBlob);

                this.setState({
                    dataSource : this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs),
                    isLoaded   : true, 
                });

            }).done();
    }, 
    render: function() {

        if (!this.state.isLoaded) {
            return this.renderLoadingView();
        }

        return this.renderListView();
    }, 
    renderLoadingView: function() {
        return (
            <View style={styles.container}>
                <ActivityIndicatorIOS
                    animating={!this.state.isLoaded}
                    style={[styles.activityIndicator, {height: 80}]}
                    size="large" />
            </View>
        );
    }, 
    renderListView: function() {
        return (
            <View style={styles.container}>
                <ListView
                    dataSource = {this.state.dataSource}
                    initialListSize = {4}
                    pageSize={4}
                    renderRow  = {this.renderRow} />
            </View>
        );
    }, 
    renderRow: function (rowData, sectionID, rowID) {
        console.log("Getting my rows on");
        console.log(rowID);
        console.log(rowData);

        var that = this;
        //call to api to get articles from rss/api var Articles 
        return <ArticleView
                category={'Music'}
                key={sectionID}
                heartText={'2.9k'}
                categoryPress={() => { that.dummy }}
                selected={false}
                source={{uri: rowData.mediaGroups[0].contents[0].url }}
                text={rowData.title}
                onPress={() => { that.dummy }} />

    },
    dummy: function() {

    }, 
    /*
    onChange: function(event, articles) {
        this.setState({articles: articles}); //trigers re-render of component
    }
    */

});


styles = StyleSheet.create({
    container: {
        flex: 1, 
        alignItems: 'center', 
        justifyContent: 'center',
    }, 
    activityIndicator: {
        alignItems: 'center',
        justifyContent: 'center',
    },
});