React Native FlatList 获得无限循环 onRefresh [英] React Native FlatList gets infinity loop onRefresh

查看:40
本文介绍了React Native FlatList 获得无限循环 onRefresh的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从 redux 获取数据到 FlatList 并且 onRefresh={} 给了我一个无限循环.当我不使用 redux 时它可以工作,但是当我将我的提取移动到 redux 操作时,我感到困惑.

Im trying to fetch data from redux to a FlatList and onRefresh={} gives me an infinity loop. When i dont use redux it works but when i moved my fetching into a redux action im getting confused.

有人可以向我描述我做错了什么吗?

Can someone describe to me what I am doing wrong?

提前致谢.

使用我的零食:https://snack.expo.io/@thesvarta/redux-with-flatlist

这是我的组件

    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import {
      View,
      Text,
      FlatList,
      StatusBar,
      StyleSheet,
      ActivityIndicator,
      TouchableOpacity,
      TouchableHighlight,
      Image,
      Button,
      SearchBar,
      TextInput,
    } from 'react-native';
    import TextDetails from '../TextDetails/TextDetails';
    import {
      fetchDataOptions,
      resetDataOptions,
      selectOptions,
    } from '../store/actions/index';
    class Search extends Component {
      constructor(props) {
        super(props);
        this.state = {
          page: 1,
          loading: false,
          refreshing: false,
        };
      }
      componentDidMount() {
        this.props.onResetDataOptions();
        this.props.onFetchDataOptions(this.state.page, this.props.GroupBy);
        console.log('component_data', this.props.fetch_data_options);
      }
      handleRefresh = () => {
        this.props.onResetDataOptions(); // Resets fetch_data_options
        this.setState(
          {
            page: 1,
            refreshing: true,
          },
          () => {
            this.props.onFetchDataOptions(this.state.page, this.props.GroupBy);
          }
        );
      };

      handleLoadMore = () => {
        if (!this.props.fetch_data_error) {
          this.setState(
            {
              page: this.state.page + 1,
            },
            () => {
              this.props.onFetchDataOptions(this.state.page, this.props.GroupBy);
              console.log('load_more', this.state.page);
            }
          );
        } else {
          this.setState(
            {
              page: 1,
            },
            () => {
              this.props.onFetchDataOptions(this.state.page, this.props.GroupBy);
              console.log('load_more_error', this.state.page);
            }
          );
        }
      };

      renderSeparator = () => {
        return (
          <View
            style={{
              height: 1,
              width: '100%',
              backgroundColor: '#CED0CE',
            }}
          />
        );
      };
      renderFooter = () => {
        if (!this.state.loading) return null;
        return (
          <View
            style={{
              paddingVertical: 20,
              borderTopWidth: 1,
              borderColor: '#CED0CE',
            }}>
            <ActivityIndicator animating size="large" />
          </View>
        );
      };

      renderRow = ({ item, index }) => {
        return (
          <View style={styles.ListContainer}>
            <View style={styles.Text}>
              <TextDetails Size={18}>{item.name}</TextDetails>
            </View>
          </View>
        );
      };
      render() {
        return (
          <View style={styles.SearchContatiner}>
            <View style={styles.Search}>
              <View style={styles.ImageIcon}>
                <Image
                  style={styles.Image}
                  resizeMode="contain"
                  source={require('../images/sokbla.png')}
                />
              </View>
              <View style={styles.InputBox}>
                <TextInput
                  style={styles.InputText}
                  onChangeText={text => this.setState({ query: text })}
                  placeholder={'Search for ' + this.props.Title}
                  value={this.state.query}
                />
              </View>
              <TouchableOpacity
                onPress={() => alert("remove query")}
                style={styles.KryssIcon}>
                <Image
                  style={styles.ImageKryss}
                  resizeMode="contain"
                  source={require('../images/kryssbla.png')}
                />
              </TouchableOpacity>
            </View>
            <View style={styles.Lista}>
              <FlatList
                style={styles.Flatlist}
                data={this.props.fetch_data_options}
                renderItem={this.renderRow}
                keyExtractor={item => item.name}
                ItemSeparatorComponent={this.renderSeparator}
                ListFooterComponent={this.renderFooter}
                onRefresh={this.handleRefresh}
                refreshing={this.state.refreshing}
                onEndReached={this.handleLoadMore}
                onEndReachedThreshold={0}
              />
            </View>
          </View>
        );
      }
    }
    const styles = StyleSheet.create({
      Lista: {
        marginTop: 20,
      },
      Flatlist: {
        width: '100%',
        height: 300,
      },
      ListContainer: {
        flexDirection: 'row',
        width: '100%',
        height: 40,
      },
      Text: {
        marginLeft: '10%',
        width: '70%',
        justifyContent: 'center',
      },
      SearchContatiner: {},
      Search: {
        width: '100%',
        height: 60,
        backgroundColor: 'rgb(240,240,240)',
        flexDirection: 'row',
      },
      Image: {
        width: 23,
        height: 33,
      },
      ImageIcon: {
        justifyContent: 'center',
        width: '15%',
        alignItems: 'center',
      },
      InputBox: {
        width: '70%',
        justifyContent: 'center',
      },
      InputText: {
        paddingLeft: 20,
        width: '100%',
        height: 50,
        fontSize: 20,
      },
      KryssIcon: {
        justifyContent: 'center',
        width: '15%',
        alignItems: 'center',
      },
      ImageKryss: {
        width: 18,
        height: 28,
      },
    });
    const mapStateToProps = state => {
      return {
        fetch_data_options: state.filter.fetch_data_options,
        fetch_data_error: state.filter.error,
        status: state.filter.status,

      };
    };
    const mapDispatchToProps = dispatch => {
      return {
        onFetchDataOptions: (page, group_by) =>
          dispatch(fetchDataOptions(page, group_by)),
        onResetDataOptions: () => dispatch(resetDataOptions()),

      };
    };
    export default connect(
      mapStateToProps,
      mapDispatchToProps
    )(Search);

这是我的行动

    import {
      FETCHING_DATA_OPTIONS,
      FETCH_DATA_OPTIONS_SUCCESS,
      FETCH_DATA_OPTIONS_FAILURE,
      FETCH_DATA_OPTIONS_RESET,
    } from './actionTypes';

    export const fetchDataOptions = (page, group_by) => {
      return dispatch => {
        dispatch(getDataOptions());
        return fetch(
          'https://ollenorstrom.se/ollenorstrom.se/avoka/api/getOptions.php?page=' +
            page +
            '&row_per_page=5&group_by=' +
            group_by
        )
          .then(res => res.json())
          .then(json => {
            //$json[0] containts .DATA, .STATUS, .MESSAGE
            //.STATUS can be 200 or 404, if its 404 it means that .DATA is empty              
            if (json[0].STATUS == 200) {
              return dispatch(
                getDataOptionsSuccess(json[0]),
                console.log('fetched_data', json[0])
              );
            } else {
              return dispatch(getDataOptionsFailure());
            }
          })
          .catch(err => dispatch(getDataOptionsFailure(err)));
      };
    };
    export const resetDataOptions = () => {
      return {
        type: FETCH_DATA_OPTIONS_RESET
      };
    };
    function getDataOptions() {
      return {
        type: FETCHING_DATA_OPTIONS,
      };
    }
    function getDataOptionsSuccess(data) {
      return {
        type: FETCH_DATA_OPTIONS_SUCCESS,
        data: data.DATA,
        status: data.STATUS
      };
    }
    function getDataOptionsFailure() {
      return {
        type: FETCH_DATA_OPTIONS_FAILURE,
      };
    }

推荐答案

您在调度 API 调用后没有更改 refreshing 状态变量的值.它在您的 handleRefresh 函数中设置为 true,但永远不会设置回 false.

You haven't changed the value of refreshing state variable after dispatching the API call. It's set as true in your handleRefresh function but never set back to false.

使用生命周期方法 componentWIllUpdatecomponentDidUpdate 之一来检查 props 是否发生变化(API 调用成功或失败),并更改你的 的状态将变量刷新为false.

Use one of the lifecycle methods componentWIllUpdate or componentDidUpdate to check whether the props have changed (API call success or fail), and change the state of your refreshing variable to false.

例如.在您的搜索组件中添加这个,

For eg. in your Search component add this,

componentDidUpdate(prevProps) {
  //Check whether props have changed and isFetching is false
  if (this.props.isFetching !== prevProps.isFetching && !this.props.isFetching) {
    this.setState({refreshing:false});
  }
}

还要检查 onEndReachedThreshold 的值是否为 0.用法说明 这里

Also check the value of onEndReachedThreshold is 0. Usage is explained here

这篇关于React Native FlatList 获得无限循环 onRefresh的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆