8.2节做完后不显示数据,最热跟趋势模块一直是正在加载更多
来源:9-1 基于多数据存储设计思想实现FavoriteDao,封装BaseItem【思考与实践】
L0ganic
2018-12-31
已经在调试了,不报错,控制台信息如下:
我的PopularItem.js:
import React, {Component} from 'react';
import {FlatList, StyleSheet, ActivityIndicator, View, RefreshControl, Text} from 'react-native';
import {connect} from 'react-redux';
import actions from '../action/index';
import {createMaterialTopTabNavigator, createAppContainer} from "react-navigation";
import NavigationUtil from '../navigator/NavigationUtil';
import PopularItem from '../common/PopularItem';
import Toast from 'react-native-easy-toast';
import NavigationBar from '../common/NavigationBar';
const URL = 'https://api.github.com/search/repositories?q=';
const QUERY_STR = '&sort=stars';
const THEME_COLOR = '#678';
import {DeviceInfo} from 'react-native';
type Props = {};
export default class PopularPage extends Component<Props> {
constructor(props) {
super(props);
console.log(NavigationUtil.navigation);
this.tabNames = ['Java', 'Android', 'ios', 'React', 'React Native', 'PHP'];
}
_genTabs() {
const tabs = {};
this.tabNames.forEach((item, index) => {
tabs[`tab${index}`] = {
screen: props => <PopularTabPage {...props} tabLabel={item} />,
navigationOptions: {
title: item
}
}
});
return tabs;
}
render() {
let statusBar = {
backgroundColor: THEME_COLOR,
barStyle: 'light-content',
};
let navigationBar = <NavigationBar
title = {'最热'}
statusBar = {statusBar}
style = {{backgroundColor: THEME_COLOR}}
/>;
const TabNavigator = createAppContainer(createMaterialTopTabNavigator(
this._genTabs(), {
tabBarOptions: {
tabStyle: styles.tabStyle,
upperCaseLabel: false, // 标签是否大写
scrollEnabled: true, // 是否支持滚动
style: {
backgroundColor: '#678', // TabBar的背景颜色
height: 30 // fix 开始scrollEnabled后在Android上初次加载闪烁的问题
},
indicatorStyle: styles.indicatorStyle, // 标签指示器的样式
labelStyle: styles.labelStyle, // 文字的样式
}
}
));
return <View style={{flex:1, marginTop: DeviceInfo.isIPhoneX_deprecated ? 30 : 0}}>
{navigationBar}
<TabNavigator />
</View>
}
}
const pageSize = 10; // 设置常量, 防止修改
class PopularTab extends Component<Props> {
constructor(props) {
super(props);
const {tabLabel} = this.props;
this.storeName = tabLabel; // react native的关键字,例如java,php,android等
}
componentDidMount() {
this.loadData();
}
loadData(loadMore) {
const {onRefreshPopular, onLoadMorePopular} = this.props;
const store = this._store();
const url = this.genFetchUrl(this.storeName);
if (loadMore) {
onLoadMorePopular(this.storeName, ++store.pageIndex, pageSize, store.items, callback => {
this.refs.toast.show('没有更多了');
})
} else {
onRefreshPopular(this.storeName, url, pageSize)
}
}
/**
* 获取与当前页面有关的数据
* @returns {*}
* @private
*/
_store() {
const {popular} = this.props;
let store = popular[this.storeName];
if (!store) {
store = {
items: [],
isLoading: false,
projectModes: [],//要显示的数据
hideLoadingMore: true,//默认隐藏加载更多
}
}
return store;
}
genFetchUrl(key) {
return URL + key + QUERY_STR;
}
renderItem(data) {
const item = data.item;
return <PopularItem
projectModel = {item}
onSelect = {() => {
NavigationUtil.goPage({
projectModes: item
}, 'DetailPage')
}}
/>
}
genIndicator() {
return this._store().hideLoadingMore ? null :
<View style={styles.indicatorContainer}>
<ActivityIndicator
style={styles.indicator}
/>
<Text>正在加载更多</Text>
</View>
}
render() {
let store = this._store();
return (
<View style={styles.container}>
<FlatList
data={store.projectModes}
renderItem={data => this.renderItem(data)}
keyExtractor={item => "" + item.id}
refreshControl={
<RefreshControl
title = {'Loading'}
titleColor = {THEME_COLOR}
colors = {[THEME_COLOR]}
refreshing = {store.isLoading}
onRefresh = {() => this.loadData()}
tintColor = {THEME_COLOR}
/>
}
ListFooterComponent={() => this.genIndicator()}
onEndReached = {() => {
console.log('---onEndReached----');
setTimeout(() => {
if (this.canLoadMore) {//fix 滚动时两次调用onEndReached https://github.com/facebook/react-native/issues/14015
this.loadData(true);
this.canLoadMore = false;
}
}, 100);
if (this.canLoadMore) {
this.loadData(true);
this.canLoadMore = false;
}
}}
onEndReachedThreshold={0.5}
onMomentumScrollBegin={() => {
this.canLoadMore = true; //fix 初始化时页调用onEndReached的问题
console.log('---onMomentumScrollBegin-----')
}}
/>
<Toast ref={'toast'}
position={'center'}
/>
</View>
);
}
}
const mapStateToProps = state => ({
popular: state.popular
});
const mapDispatchToProps = dispatch => ({
//将 dispatch(onRefreshPopular(storeName, url))绑定到props
onRefreshPopular: (storeName, url, pageSize) => dispatch(actions.onRefreshPopular(storeName, url, pageSize)),
onLoadMorePopular: (storeName, pageIndex, pageSize, items, callBack) => dispatch(actions.onLoadMorePopular(storeName, pageIndex, pageSize, items, callBack)),
});
//注意:connect只是个function,并不应定非要放在export后面
const PopularTabPage = connect(mapStateToProps, mapDispatchToProps)(PopularTab);
const styles = StyleSheet.create({
container: {
flex: 1,
},
tabStyle: {
//minWidth: 50
padding: 0
},
indicatorStyle: {
height: 2,
backgroundColor: 'white'
},
labelStyle: {
fontSize: 13,
margin: 0,
},
indicatorContainer: {
alignItems: "center"
},
indicator: {
color: 'red',
margin: 10
}
});
我的PopularItem.js:
import React from 'react';
import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import BaseItem from "./BaseItem";
export default class PopularItem extends BaseItem {
render() {
const {projectModel} = this.props;
const {item} = projectModel;
if (!item || !item.owner) {
return null;
}
return (
<TouchableOpacity
onPress = {this.props.onSelect}
>
<View style={styles.cell_container}>
<Text style = {styles.title}>
{item.full_name}
</Text>
<Text style = {styles.description}>
{item.description}
</Text>
<View style = {styles.row}>
<View style = {styles.row}>
<Text>Author:</Text>
<Image style={{height: 22, width: 22}}
source={{uri: item.owner.avatar_url}}
/>
</View>
<View style = {{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text>Star:</Text>
<Text>{item.stargazers_count}</Text>
</View>
{this._favoriteIcon()}
</View>
</View>
</TouchableOpacity>
)
}
}
const styles = StyleSheet.create({
cell_container: {
backgroundColor: 'white',
padding: 10,
marginLeft: 5,
marginRight: 5,
marginVertical: 3,
borderColor: '#dddddd',
borderWidth: 0.5,
borderRadius: 2,
shadowColor: 'gray',
shadowOffset: {width: 0.5, height: 0.5},
shadowOpacity: 0.4,
shadowRadius: 1,
elevation: 2
},
row: {
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
},
title: {
fontSize: 16,
marginBottom: 2,
color: '#212121',
},
description: {
fontSize: 14,
marginBottom: 2,
color: '#757575',
}
}
);
我的BaseItem.js:
import React, {Component} from 'react';
import {Image, StyleSheet, Text, TouchableOpacity, View,} from 'react-native'
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import HTMLView from 'react-native-htmlview';
import {PropTypes} from 'prop-types';
export default class BaseItem extends Component {
static propTypes = {
projectModel: PropTypes.object,
onSelect: PropTypes.func,
onFavorite: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
isFavorite: this.props.projectModel.isFavorite,
}
}
/**
* 牢记:https://github.com/reactjs/rfcs/blob/master/text/0006-static-lifecycle-methods.md
* componentWillReceiveProps在新版React中不能再用了
* @param nextProps
* @param prevState
* @returns {*}
*/
static getDerivedStateFromProps(nextProps, prevState) {
const isFavorite = nextProps.projectModel.isFavorite;
if (prevState.isFavorite !== isFavorite) {
return {
isFavorite: isFavorite,
};
}
return null;
}
setFavoriteState(isFavorite) {
this.props.projectModel.isFavorite = isFavorite;
this.setState({
isFavorite: isFavorite,
})
}
onPressFavorite() {
this.setFavoriteState(!this.state.isFavorite);
this.props.onFavorite(this.props.projectModel.item, !this.state.isFavorite)
}
_favoriteIcon() {
const {theme} = this.props;
return <TouchableOpacity
style={{padding: 6}}
underlayColor='transparent'
onPress={() => this.onPressFavorite()}>
<FontAwesome
name={this.state.isFavorite ? 'star' : 'star-o'}
size={26}
style={{color: theme.themeColor}}
/>
</TouchableOpacity>
}
}
最怕这种不报错的,希望老师帮我看看, 谢谢啦!
写回答
1回答
-
CrazyCodeBoy
2019-01-01
遇到不报错的问题也不要怕哈,老师教你遇到类似的问题的解决思路:
第一步:开启debug模式,在触发加载数据action的地方(可以是loadData方法中)打个断点后写个debugger;
第二步:在对应的action目录下的对应action中打断点,跟踪最后一次dispatch是否有数据;
第三步:在对应的reducer中打断点,看是否正确取出action发过来的数据;
第四步:在最热页面的PopularTab的render方法中打个断点,看最后一次reducer返回后,是否有收到对应的props。
切记,reducer取数据的字段要和action所发出去数据的字段保持一致,render中从props中取的字段要和reducer返回的字段保持一致;
另外在分享一个Chrome 开发者工具的官方教程,建议多看看哈,对调试代码很有帮助:
https://developers.google.com/web/tools/chrome-devtools/
最后,如果通过上述步骤还是定位不到问题,可以在我们的课程群中加老师好友,我帮你继续分析出错的原因哈。
00
相似问题
fetchdata()是什么方法?
回答 1
最热模块
回答 1