首页 > 解决方案 > Firebase无限滚动正确的解决方案?

问题描述

我在一个组件中构建了一个非常复杂的列表,所有查询都以相同的方式进行。当我到达列表的末尾时,我将获取限制增加了 10... 一切都很顺利,直到我意识到我正在重新加载所有数据(不仅仅是新的 10 个)。我想避免所有这些读取以降低成本-我不确定firebase是否会忽略已加载的数据...当我每次获取额外的 10 个时,我的列表运行得非常顺利,但我不知道是否幕后的事情会回来困扰我!

更新

我根据一些有用的反馈更新了我的代码,我相信我的工作应该是这样的。我只关心一件事。当我在第一次获取后到达列表的底部时,我会将所有以前的数据传递给我的动作创建者,然后将其连接到新的获取数据。随着列表的增长,每次我触底时都会重复这种情况。我的列表将有超过 1000 条记录,所以我担心潜在的性能问题,应该这样吗?在下面看看我的新尝试!

原始尝试:

onEndReached = () => {
 const { searchFilterText, effectVal } = this.state;

   this.setState({
     strainFetchIndex: this.state.strainFetchIndex + 10
   }, () => {
     const offset = this.state.strainFetchIndex;

      if (searchFilterText === '') {
       this.props.strainsFetch(offset);
     } else if (searchFilterText === 'Hybrid' || searchFilterText === 'Salt' || searchFilterText === 'Initial') {
       this.props.filterStrainAction(searchFilterText, offset);
     } else if (searchFilterText === 'Effects') {
       this.props.filterByEffect(effectVal, offset);
     }
  });
}

//HERES 1 of 4 ACTION CREATORS WHERE I FETCH MORE DATA (ALL ARE SIMILAR)

    export const strainsFetch = (offset) => {
      const ting = offset || 1;
        return (dispatch) => {
          firebase.database().ref('/strains')
            .orderByKey()
            .limitToFirst(1 * ting)
            .on('value', snapshot => {
              dispatch({ type: STRAINS_FETCH_SUCCESS, payload: snapshot.val() });
            });
        };
      };

新尝试:

  onEndReached = () => {
    const { searchFilterText } = this.state;
    const { lastKey } = this.props;
    const currentStrains = this.props.strains;

      if (this.state.filterLabel === 'Favourites') {
        return null;
      }
      if (searchFilterText === '') {
        //here I pass all previous records along with the last key (last key comes from my action creator)
        this.props.strainsFetch(currentStrains, lastKey);
      } 
    }



    //ACTION CREATOR



    export const strainsFetch = (currentStrains, lastKey) => {
      if (!lastKey) {
        return (dispatch) => {
          // console.log('first Fetch');
          firebase.database().ref('/strains')
            .orderByKey()
            .limitToFirst(10)
            .on('value', snapshot => {
              const snap = snapshot.val();
              const snapKeys = Object.keys(snap);
              const createLastKey = snapKeys[9];

              dispatch({ type: STRAINS_FETCH_SUCCESS, payload: snapshot.val(), key: createLastKey });
            });
        };
      }
        return (dispatch) => {
          // console.log('subsequent Fetch');
          firebase.database().ref('/strains')
            .orderByKey()
            .startAt(`${lastKey}`)
            .limitToFirst(11)
            .on('value', snapshot => {
              const snap = snapshot.val();
              const snapKeys = Object.keys(snap)
              .slice(1);

              const results = snapKeys
                 .map((key) => snapshot.val()[key]);

              const createLastKey = snapKeys[snapKeys.length - 1];
              const concatStrains = _.concat(currentStrains, results);

              dispatch({ type: STRAINS_FETCH_SUCCESS, payload: concatStrains, key: createLastKey });
            });
        };
      };



      //HERE IS WHAT MY REDUCER LOOKS LIKE



    import {
      STRAINS_FETCH_SUCCESS
    } from '../actions/types';

    const INITIAL_STATE = {};

    export default (state = INITIAL_STATE, action) => {
      switch (action.type) {
        case STRAINS_FETCH_SUCCESS:
        // console.log(action.payload);
          return { strains: action.payload, lastKey: action.key };

        default:
          return state;
      }
    };

随着列表的不断增长,一遍又一遍地将以前的数据传递给我的动作创建者,这是一种不好的做法吗?还是有更有效的方法来实现这一点?

感谢大家!

干杯。

标签: reactjsfirebasefirebase-realtime-database

解决方案


您是正确的,因为除了新的之外,您还重新加载了所有旧的。如果您只想加载新的,那么您应该使用该.startAt()方法,在此处查看相关文档

您的最终设置如下所示:

export const strainsFetch = (offset) => {
    const startingIndex = offset || 1;
    const numRecordsToLoad = 10;
    return (dispatch) => {
        firebase.database().ref('/strains')
            .orderByKey()
            .startAt(startingIndex)
            .limitToFirst(numRecordsToLoad)
            .on('value', snapshot => {
                dispatch({ type: STRAINS_FETCH_SUCCESS, payload: snapshot.val() });
            });
    };
};

推荐阅读