React native,Redux:获取更多/加载更多

时间:2018-07-03 00:38:08

标签: reactjs react-native redux react-native-flatlist

我认为我的问题与redux有关。行为是当我到达loadmore项目(onEndReached)的底部时,滚动将回到顶部,而不是保持位置并添加item.It添加项目,但就像我说的,我回到顶部。预期的行为将是onEndReach必须保持位置而不是重新加载所有项目。我在此存储库中有以下简单代码:https://github.com/francoro/flatlistRedux 我将把代码也放在这里:

PostsList.js

import React, { Component } from 'react';
import { View, Image, FlatList, ListView, Text } from 'react-native';
import { connect } from 'react-redux';
import { fetchData } from './actions';
import { emptyData } from './actions';
class Login extends Component {
  constructor() {
    super();
    this.position = 0;
  }

  componentWillMount() {
    this.props.emptyData();
    this.props.fetchData(this.props.tabId, 0, this.props.dateFilter, this.position);
  }

  /* componentWillReceiveProps(newProps) {
    if (newProps.dateFilter !== this.props.dateFilter || newProps.tabId !== this.props.tabId) {
      this.position = 0;
      this.props.emptyData();
      this.props.fetchData(newProps.tabId, 0, newProps.dateFilter, this.position);
    }
  } */

  handleLoadMore = () => {
    this.position += 10;
    if (this.props.posts.data.total === this.props.posts.data.posts.length) {
      console.log("ALL LOADED")
      return
    }
    console.log("POSITION", this.position)
    this.props.fetchData(this.props.tabId, 0, this.props.dateFilter, this.position);

  };

  renderRow({ item }) {
    return (
      <View>
        <Text>{item._id}</Text>
        <Image style={{ width: 200, height: 400 }} source={{ uri: item.image }} />
        <Text>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</Text>
      </View>
    );
  }

  render() {
    return (
      <View>
        <FlatList
          data={this.props.posts.data.posts}
          renderItem={this.renderRow}
          onEndReached={this.handleLoadMore}
          keyExtractor={item => item._id}
          onEndReachedThreshold={0.5}
        />
      </View>
    )
  }
}

const mapStateToProps = state => {
  return {
      posts: state.dataReducer,
      tabId: state.tabId,
      dateFilter: state.dateFilter
  }
}

const mapDispatchToProps = dispatch => {
  return {
      fetchData: (type, filter, dateFilter, position) => dispatch(fetchData(type, filter, dateFilter, position)),
      emptyData: () => dispatch(emptyData())
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Login)

我的App.js

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';
import { Provider } from 'react-redux';
import configureStore from './src/configureStore';
import PostsList from './src/PostsList.js';

let store = configureStore();

export default class App extends Component<Props> {
  render() {
    return (
      <Provider store={store}>
        <View>
          <PostsList />
        </View>
      </Provider>
    );
  }
}

configureStore.js

import {createStore, applyMiddleware} from 'redux';
import reducers from './reducers';
import thunk from "redux-thunk";

export default configureStore = () => {
    let store = createStore(reducers, applyMiddleware(thunk));
    return store;
}

actions / index.js

import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from "../constants"
import getDataApi from '../api';

export const getData = () => {
    return {
        type: FETCHING_DATA
    }
}


export const getDataSuccess = (newData, initialData = null) => {
    return {
        type: FETCHING_DATA_SUCCESS,
        newData,
        initialData
    }
}

export const getDataFailure = () => {
    return {
        type: FETCHING_DATA_FAILURE
    }
}

export const emptyDataStore = () => {
    return {
        type: 'EMPTY_DATA'
    }
}

export const fetchData = (type, filter, dateFilter, position) => {
    return (dispatch, getState) => {
        const state = getState();

        dispatch(getData())
        getDataApi(type, filter, dateFilter, position)
            .then(res => {
                console.log("RES", res)
                if (res !== false) {
                    console.log("entro")
                    if (state.dataReducer.data.length === 0) {
                        dispatch(getDataSuccess(res[1]))
                    } else {
                        dispatch(getDataSuccess(res[1], state.dataReducer.data))
                    }

                }

            })
            .catch((err) => console.log(9999, err))
    }
}

export const emptyData = () => {
    return (dispatch) => {
        dispatch(emptyDataStore())
    }
}

api / index.js

const URL = "https://still-gorge-30183.herokuapp.com";
let fetching = false;

export default (type, filter, dateFilter, position) => {
    if (fetching) return Promise.reject(new Error('Request in progress'));
    console.log("URLl", `/search/${type}/${filter}/${dateFilter}/${position}/0/0`)
    fetching = true;
    return fetch(URL + `/search/${type}/${filter}/${dateFilter}/${position}/0/0`)
        .then(response => Promise.all([response, response.json()]))
        .then(([response, responseObj]) => {
            fetching = false;
            return [response, responseObj];
        })
        .catch(err => {
            fetching = false;
            return Promise.reject(err);
          })

}

reducers / dataReducer.js

import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE, EMPTY_DATA } from '../constants';

const initialState = {
    data: [],
    isFetching: false,
    error: false,
}

export default dataReducer = (state = initialState, action) => {
    switch (action.type) {
        case EMPTY_DATA:
            return {
                ...state,
                data: []
            }
        case FETCHING_DATA:
            return {
                ...state,
                data: [],
                isFetching: true
            }
        case FETCHING_DATA_SUCCESS:
            if (action.initialData === null) {
                return {
                    ...state,
                    data: action.newData,
                    isFetching: false
                }
            } else {
                let concatResult = {};
                concatResult.total = action.newData.total;
                concatResult.posts = action.initialData.posts.concat(action.newData.posts);
                return {
                    ...state,
                    data: concatResult,
                    isFetching: false
                }
            }

        case FETCHING_DATA_FAILURE:
            return {
                ...state,
                isFetching: false,
                error: true
            }
        default:
            return state
    }
}

也许这与我在dataReducer.js中进行concat的方式有关,我不知道这是否是处理Redux中更多负载的正确方式。 感谢您的阅读。

1 个答案:

答案 0 :(得分:1)

我认为问题在于您创建新数据,而不是将其concat替换为旧数据

concatResult.posts = action.initialData.posts.concat(action.newData.posts);

尝试进入concat状态,例如

concatResult.posts = state.data.posts.concat(action.newData.posts);