我试图将数据从redux提取到FlatList,而onRefresh = {}给了我无限循环。当我不使用redux时,它可以工作,但是当我将获取内容移入redux动作时,我会感到困惑。
有人可以向我描述我在做什么错吗?
谢谢。
使用我的小吃: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,
};
}
答案 0 :(得分:1)
分派API调用后,您尚未更改refreshing
状态变量的值。在您的true
函数中将其设置为handleRefresh
,但永远不要设置回false
。
使用生命周期方法componentWIllUpdate
或componentDidUpdate
之一来检查道具是否已更改(API调用成功或失败),并将refreshing
变量的状态更改为false。
例如在您的搜索组件中添加此内容,
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。用法说明here