i make a side menu,it's ok on genymotion,but not work on my phone. it's response is delay more than 10s and most times not response on phone。please help me !
At the beginning ,I think it's flow reason:
1、position: 'absolute'
2、PanResponder wrapper a touchable
i had try clean this,but it's also not work。maybe its a bug ,are you ?
enter image description here
import React, {Component} from 'react'
import {
View,
Text,
StyleSheet,
ScrollView,
Alert,
PanResponder,
TouchableOpacity
} from 'react-native'
import {get_pointBaikeCate} from 'api'
import {Touchable} from 'basic'
export default class PointBaike extends Component {
static navigationOptions = {
title: '穴位百科',
header: null
}
constructor(props) {
super(props);
this.state = {
info: []
}
this.scrollY = []
}
async getInfo() {
let res = await get_pointBaikeCate();
console.log(res)
// let info = [];
// res.data.map((r)=> {
// r.content.map(c=> {
// let flag = info.find((item)=> {
// return item.jl == c.jl
// })
// if (flag) {
// flag.xw += `,${c.xw}`
// } else {
// info.push({
// jl: c.jl,
// xw: c.xw
// })
// }
// })
// });
//
// // 对info的xw进行过滤
// info = info.map((item)=> {
// let xw = item.xw.split(/[,|]/)
// item.xw = [...new Set(xw)].filter((x)=> {
// return x
// })
// return item
// });
this.setState({
info: res.data
})
}
goDetail(item) {
let {navigate} = this.props.navigation
console.log(item)
navigate('PointBaikeDetail', {
item
})
}
componentWillMount() {
this.getInfo()
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder.bind(this),
onStartShouldSetPanResponderCapture: this._handleStartShouldSetPanResponderCapture.bind(this),
onMoveShouldSetPanResponder: this._handlerMoveShouldSetPanResponder.bind(this),
onMoveShouldSetPanResponderCapture: this._handleMoveShouldSetPanResponderCapture.bind(this),
onPanResponderTerminationRequest: this._handleMoveShouldSetPanResponderCapture,
onPanResponderMove: this._handlePanResponderMove.bind(this),
});
}
_handlerMoveShouldSetPanResponder(evt, gestureState){
if (gestureState.dx != 0 && gestureState.dy == 0) {
return true;
}
return false;
}
_handleMoveShouldSetPanResponderCapture(evt, gestureState) {
return gestureState.dx != 0 && gestureState.dy != 0
}
_handleStartShouldSetPanResponderCapture(evt, gestureState) {
return gestureState.dx != 0 && gestureState.dy != 0;
}
_handleMoveShouldSetPanResponderCapture(evt, gestureState) {
return gestureState.dx != 0 && gestureState.dy != 0;
}
_scrollTo(index) {
// Alert.alert('索引', `${index}`)
this._scrollView.scrollTo({y: this.scrollY[index]})
}
_handleStartShouldSetPanResponder() {
return true
}
_handlePanResponderMove(e, gestureState) {
// console.log('滑动', e.nativeEvent.pageY)
// 计算手指在那个元素上,得出index,然后根据index设置scrollTop
let y = e.nativeEvent.pageY - 100
let index = Math.ceil(y / 20) - 1
console.log(index, this)
this._scrollView.scrollTo({y: this.scrollY[index]})
}
_onLayout({nativeEvent}) {
this.scrollY.push(nativeEvent.layout.y)
}
render() {
let {info} = this.state
return (
<View style={styles.wrapper}>
<ScrollView style={{flex: 1, height: 300}}
showsVerticalScrollIndicator={false}
ref={(e)=> {
this._scrollView = e
}}
>
{
info.map((item, i)=> {
return (
<View key={i} style={styles.lists}
onLayout={this._onLayout.bind(this)}
>
<View>
<Text style={styles.title}>{item.title}</Text>
</View>
<View style={styles.listBox}>
{
item.list.map((x, xi)=> {
return (
<Touchable key={xi}
onPress={this.goDetail.bind(this, x)}
>
<View style={styles.list}>
<Text
style={styles.text}>{x.title}</Text>
</View>
</Touchable>
)
})
}
</View>
</View>
)
})
}
<View style={{height: 100}}></View>
</ScrollView>
<View style={styles.sideMenu}
{...this._panResponder.panHandlers}
>
{
info.map((item, i)=> {
return (
<TouchableOpacity key={i} onPress={this._scrollTo.bind(this, i)}>
<View>
<Text
style={styles.sideText}>{item.title.charAt(3) || item.title.charAt(0)}</Text>
</View>
</TouchableOpacity>
)
})
}
</View>
</View>
)
}
}
const styles = StyleSheet.create({
wrapper: {
paddingLeft: 6,
paddingRight: 6,
paddingTop: 10,
paddingBottom: 10,
flex: 1,
backgroundColor: '#fff'
},
sideText: {
width: 25,
height: 20,
lineHeight: 20,
textAlign: 'center'
},
sideMenu: {
position: 'absolute',
right: 0,
top: 100,
zIndex: 100,
backgroundColor: '#eee'
},
lists: {},
listBox: {
flexDirection: 'row',
flexWrap: 'wrap'
},
list: {
width: (WinWidth - 20) / 5,
},
title: {
fontSize: 18,
color: DEFAULT_COLOR,
paddingTop: 14,
paddingBottom: 10
},
text: {
flex: 1,
textAlign: 'center',
paddingTop: 10,
paddingBottom: 10,
}
})
you can try this
componentWillMount() {
this.getInfo()
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onStartShouldSetPanResponderCapture: this._handleStartShouldSetPanResponderCapture.bind(this),
onMoveShouldSetPanResponder: this._handlerMoveShouldSetPanResponder.bind(this),
onMoveShouldSetPanResponderCapture: this._handleMoveShouldSetPanResponderCapture.bind(this),
onPanResponderTerminationRequest: this._handleMoveShouldSetPanResponderCapture,
onPanResponderMove: this._handlePanResponderMove.bind(this),
});
}
Related
For the first time when user logins, business id will be null then after WebViewPage call I am storing value in Business id and resource id. initially it don't have any value, I am confused how to handle this condition.I want to retrieve business id and resources id from DefaultPreference once its stored but I am getting above error. Any help will be appreciated.Thanks.
import React from 'react';
import {View,ImageBackground, Image, Platform} from 'react-native';
import NetInfo from "#react-native-community/netinfo"
import DefaultPreference from 'react-native-default-preference';
export default class SplashScreen extends React.Component {
constructor(props) {
super(props);
var SharedPreferences = require('react-native-shared-preferences');
if (Platform.OS === 'android') {
SharedPreferences.getItems(["business_entity_id","resorce_id","userid"],(values) => {
console.log("after");
const business_entity_id = values[0]
if (business_entity_id === null)
{
business_entity_id = ""
}
const resorce_id = values[1]
if (resorce_id === null)
{
resorce_id = ""
}
console.log(business_entity_id);
setTimeout(() => {
load();
}, 2000);
load = () => {
let internetconnection = NetInfo.addEventListener(state => {
if (state.isConnected === true)
{
console.log(business_entity_id);
if (business_entity_id == "" && resorce_id == "") {
props.navigation.navigate('PracticeCode');
}
else if(resorce_id == "")
{
props.navigation.navigate('DoctorDetails');
}
else {
console.log("next")
props.navigation.navigate('Calendar');
}
}
else {
Alert.alert("Alert",
"Please check your Internet Connection");
}
});
};
});
}
else{
setTimeout(() => {
load();
}, 2000);
load = () => {
let internetconnection = NetInfo.addEventListener(state => {
if (state.isConnected === true)
{
DefaultPreference.get('business_entity_id').then(function(value) {console.log(value)});
DefaultPreference.get('userid').then(function(value) {console.log("userid",value)});
props.navigation.navigate('PracticeCode');
}
else {
Alert.alert("Alert",
"Please check your Internet Connection");
}
});
};
}
}
render() {
return (
<View style={ {
width: '100%'
}}>
<View>
<ImageBackground source={require('./../assets/bg.jpg')} style={ {
resizeMode: "cover",
justifyContent: "center",
alignItems: 'center',
width: '100%',
height: '100%'
}}>
<View style={{
position: "absolute",
left: 0,
width: '100%',
height: '100%',
backgroundColor: '#fff',
opacity: 0.9
}}></View>
<Image style={ {
width: 250,
resizeMode: 'cover'
}} source={require('./../assets/splash.png')} />
</ImageBackground>
</View>
</View>
);
}
}
I'm updating a project to react-native 62+ from 50~, and ListView was removed from react-native, and so I'm trying to change the ListView in this file to a FlatList. I don't know what to do with datasource to properly manage the data. Can somebody help me upgrade this file?
This is the original code using the ListView without any of my attempts at upgrading, which gives "Invariant Error: ListView has been removed from React-Native": (my attempted code below)
'use strict';
import React, { Component } from 'react';
import {
ListView,
Platform,
StyleSheet,
Text,
Image,
View,
TouchableOpacity,
TouchableHighlight,
TouchableNativeFeedback,
} from 'react-native';
import PoplarEnv from '../util/PoplarEnv';
import CommentCell from './CommentCell';
import {getCommentsOfObject} from '../api/CommentAPI';
import URLConf from '../api/URLConf';
const avatar_thumbnail = '?imageView2/1/w/48/h/48';
export default class CommentList extends Component{
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
replyModalVisible: false,
commentsArray: [],
commentCounter: this.props.commentCounter,
commented: this.props.commented,
limit: this.props.limit, //评论显示行数
comment: null,
commentBarVisible: false,
};
}
componentDidMount() {
this.fetchData();
}
/*
被评论的feed类型
*/
getCommentObjType(type) {
var type_str = '';
switch (type) {
case PoplarEnv.COMMENT_OBJ_TYPE.POST:
type_str = 'post';
break;
case PoplarEnv.COMMENT_OBJ_TYPE.PHOTO:
type_str = 'photo';
break;
case PoplarEnv.COMMENT_OBJ_TYPE.ALBUM:
type_str = 'album';
break;
case PoplarEnv.COMMENT_OBJ_TYPE.SPOST:
type_str = 'spost';
break;
default:
type_str = '';
}
return type_str;
}
fetchData() {
var type_str = this.getCommentObjType(this.props.object_type);
getCommentsOfObject(type_str, this.props.object_id,this.state.limit, (result, comments) => {
this.setState({
commentsArray: comments,
dataSource: this.state.dataSource.cloneWithRows(comments),
loaded: true,
});
});
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>
Loading...
</Text>
</View>
);
}
setReplyModalVisible() {
this.setState({replyModalVisible: true});
}
setReplyModalInVisible() {
this.setState({replyModalVisible: false});
}
addNewComment(comment) {
console.log('add new comment to comments list');
console.log(comment);
var commentsArray = this.state.commentsArray;
commentsArray.push(comment);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(commentsArray),
});
}
componentWillReceiveProps(nextProps) {
if(this.props.commentCounter == nextProps.commentCounter) return;
if(nextProps.newComment != undefined && nextProps.newComment != null) {
this.addNewComment(nextProps.newComment);
}
}
render() {
if(!this.state.loaded) {
return this.renderLoadingView();
}
return this.renderCommentList(this.props.commentCounter);
}
showCommentBar() {
this.setState({
commentBarVisible: true,
});
}
hideCommentBar() {
this.setState({
isComment: false,
commentBarVisible: false,
});
}
renderCommentList(commentCounter) {
if(commentCounter > 0) {
return (
<TouchableOpacity style={styles.commentList} onPress={this.props.nav2FeedDetail}>
<ListView
dataSource={this.state.dataSource}
renderRow={(comment)=>this.renderRow(comment, this.props.caller)}
/>
</TouchableOpacity>
);
} else {
return (<View/>);
}
}
renderAuthorName(comment) {
if(comment.comment_parent_author_name != undefined && comment.comment_parent_author_name != null) {
return (<View style={{flex: 1, flexDirection: 'row'}}>
<Text style={styles.username}>{comment.comment_author_name}</Text>
<Text style={{fontSize: 14, color: '#9B9B9B', bottom: 1}}> Reply </Text>
<Text style={styles.username}>{comment.comment_parent_author_name}</Text>
</View>
);
} else {
return (<Text style={styles.username}>{comment.comment_author_name}</Text>);
}
}
renderRow(comment, caller) {
if(comment == null || comment == undefined) {
return (<View />);
} else {
if(caller == 'FeedCell') {
return(
<View style={styles.commentBox}>
<Image style={styles.avatar} source={{uri:URLConf.IMG_BASE_URL+comment.comment_author_avatar+avatar_thumbnail}} />
<View style={{flex:1}}>
{this.renderAuthorName(comment)}
<Text style={styles.comment}>{comment.comment_content}</Text>
</View>
</View>
);
} else if(caller == 'FeedDetail') {
return(
<CommentCell comment={comment} reply={this.props.reply}/>
);
}
}
}
};
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
commentList: {
marginTop: -10,
marginLeft:8,
marginRight:8,
paddingTop: 0,
},
commentBox: {
flex: 1,
flexDirection: 'row',
//borderColor: 'black',
//borderWidth: 1,
padding: 10,
paddingBottom: 4,
},
avatar: {
borderRadius: 16,
width: 32,
height: 32,
marginRight: 10,
},
username: {
fontSize: 14,
fontWeight: 'bold',
color: 'black',
// lineHeight: 13,
marginBottom: 4,
},
commentTime: {
},
comment: {
fontSize: 14,
color: '#030303',
lineHeight: 18,
},
});
module.exports = CommentList;
This is the code of my attempt at upgrading it, but I get this error "TypeError: undefined is not an object (evaluating '_this2.state.dataSource.cloneWithRows')" on line 78 "dataSource: this.state.dataSource.cloneWithRows(comments),"
'use strict';
import React, { Component } from 'react';
import {
FlatList,
//ListView,
Platform,
StyleSheet,
Text,
Image,
View,
TouchableOpacity,
TouchableHighlight,
TouchableNativeFeedback,
} from 'react-native';
import PoplarEnv from '../util/PoplarEnv';
import CommentCell from './CommentCell';
import {getCommentsOfObject} from '../api/CommentAPI';
import URLConf from '../api/URLConf';
const avatar_thumbnail = '?imageView2/1/w/48/h/48';
export default class CommentList extends Component{
constructor(props) {
super(props);
this.state = {
// dataSource: new ListView.DataSource({
// rowHasChanged: (row1, row2) => row1 !== row2,
// }),
loaded: false,
replyModalVisible: false,
commentsArray: [],
commentCounter: this.props.commentCounter,
commented: this.props.commented,
limit: this.props.limit, //评论显示行数
comment: null,
commentBarVisible: false,
};
}
componentDidMount() {
this.fetchData();
}
/*
被评论的feed类型
*/
getCommentObjType(type) {
var type_str = '';
switch (type) {
case PoplarEnv.COMMENT_OBJ_TYPE.POST:
type_str = 'post';
break;
case PoplarEnv.COMMENT_OBJ_TYPE.PHOTO:
type_str = 'photo';
break;
case PoplarEnv.COMMENT_OBJ_TYPE.ALBUM:
type_str = 'album';
break;
case PoplarEnv.COMMENT_OBJ_TYPE.SPOST:
type_str = 'spost';
break;
default:
type_str = '';
}
return type_str;
}
fetchData() {
var type_str = this.getCommentObjType(this.props.object_type);
getCommentsOfObject(type_str, this.props.object_id,this.state.limit, (result, comments) => {
this.setState({
commentsArray: comments,
dataSource: this.state.dataSource.cloneWithRows(comments),
loaded: true,
});
});
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>
Loading...
</Text>
</View>
);
}
setReplyModalVisible() {
this.setState({replyModalVisible: true});
}
setReplyModalInVisible() {
this.setState({replyModalVisible: false});
}
addNewComment(comment) {
console.log('add new comment to comments list');
console.log(comment);
var commentsArray = this.state.commentsArray;
commentsArray.push(comment);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(commentsArray),
});
}
componentWillReceiveProps(nextProps) {
if(this.props.commentCounter == nextProps.commentCounter) return;
if(nextProps.newComment != undefined && nextProps.newComment != null) {
this.addNewComment(nextProps.newComment);
}
}
render() {
if(!this.state.loaded) {
return this.renderLoadingView();
}
return this.renderCommentList(this.props.commentCounter);
}
showCommentBar() {
this.setState({
commentBarVisible: true,
});
}
hideCommentBar() {
this.setState({
isComment: false,
commentBarVisible: false,
});
}
renderCommentList(commentCounter) {
if(commentCounter > 0) {
return (
<TouchableOpacity style={styles.commentList} onPress={this.props.nav2FeedDetail}>
<FlatList
data={this.state.dataSource}
extraData={this.state}
renderItem={(comment)=>this.renderRow(comment, this.props.caller)}
/>
{/* <ListView
dataSource={this.state.dataSource}
renderRow={(comment)=>this.renderRow(comment, this.props.caller)}
/> */}
</TouchableOpacity>
);
} else {
return (<View/>);
}
}
renderAuthorName(comment) {
if(comment.comment_parent_author_name != undefined && comment.comment_parent_author_name != null) {
return (<View style={{flex: 1, flexDirection: 'row'}}>
<Text style={styles.username}>{comment.comment_author_name}</Text>
<Text style={{fontSize: 14, color: '#9B9B9B', bottom: 1}}> Reply </Text>
<Text style={styles.username}>{comment.comment_parent_author_name}</Text>
</View>
);
} else {
return (<Text style={styles.username}>{comment.comment_author_name}</Text>);
}
}
renderRow(comment, caller) {
if(comment == null || comment == undefined) {
return (<View />);
} else {
if(caller == 'FeedCell') {
return(
<View style={styles.commentBox}>
<Image style={styles.avatar} source={{uri:URLConf.IMG_BASE_URL+comment.comment_author_avatar+avatar_thumbnail}} />
<View style={{flex:1}}>
{this.renderAuthorName(comment)}
<Text style={styles.comment}>{comment.comment_content}</Text>
</View>
</View>
);
} else if(caller == 'FeedDetail') {
return(
<CommentCell comment={comment} reply={this.props.reply}/>
);
}
}
}
};
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
commentList: {
marginTop: -10,
marginLeft:8,
marginRight:8,
paddingTop: 0,
},
commentBox: {
flex: 1,
flexDirection: 'row',
//borderColor: 'black',
//borderWidth: 1,
padding: 10,
paddingBottom: 4,
},
avatar: {
borderRadius: 16,
width: 32,
height: 32,
marginRight: 10,
},
username: {
fontSize: 14,
fontWeight: 'bold',
color: 'black',
// lineHeight: 13,
marginBottom: 4,
},
commentTime: {
},
comment: {
fontSize: 14,
color: '#030303',
lineHeight: 18,
},
});
module.exports = CommentList;
If you need any more code, like CommentCell or FeedCell, just let me know and I'll edit the post to add the code. Can somebody please help me with this, I've spent hours on it.
You have to totally change ListView to Flatlist.
So first import Flatlist from the react-native :
import { FlatList } from "react-native";
Then change ListView to Flatlist as below :
renderCommentList(commentCounter) {
if(commentCounter > 0) {
return (
<TouchableOpacity style={styles.commentList} onPress={this.props.nav2FeedDetail}>
<FlatList
data={this.state.dataSource}
extraData={this.state}
renderItem={({ item })=>this.renderRow(item, this.props.caller)}
/>
</TouchableOpacity>
);
} else {
return (<View/>);
}
}
You can find more documentation here
Update
Your dataSource state variable should be simple array like this :
this.state = {
dataSource: []
}
Then when you fetch the data, append your data in dataSource state variable like this :
this.setState({
commentsArray: comments,
dataSource: comments,
loaded: true,
});
**Note : **Your renderItems method should be as below :
renderItem={({ comment })=>this.renderRow(comment, this.props.caller)}
comment should be in {} braces.
Topic: Video Flatlist in React Native. (Normal Videos / YouTube Videos)
Any one will be displayed according to the array data simultaneously. So it will be a long flatlist containing two types of video.
Sometimes many onPress event doesn't work due to performance issue
Major Issues:
App crashes when scrolling bottom to top
Performance is very poor
Above two are the major issue need to solve. Are there any ways to solve these issues?
What solutions can I try to improve Flatlist performance and to solve Video Flatlist crashing issue?
Below is my code in App.js
import React from "react";
import {
StyleSheet,
Text,
View,
SafeAreaView,
FlatList,
TouchableWithoutFeedback,
Dimensions
} from "react-native";
import Video from "react-native-video";
import ProgressBar from "react-native-progress/Bar";
import YouTube from 'react-native-youtube';
import LightVideo from "./sample.mp4";
import Icon from "react-native-vector-icons/FontAwesome";
// console.disableYellowBox = true;
function secondsToTime(time) {
return ~~(time / 60) + ":" + (time % 60 < 10 ? "0" : "") + time % 60;
}
const { width } = Dimensions.get("window");
const height = width * 0.5625;
const list = [
{
'type': 'YouTube'
},
{
'type': 'Normal'
},
{
'type': 'YouTube'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
];
export default class RNVideo extends React.PureComponent {
state = {
video: [],
duration: [0, 0, 0, 0, 0],
progress: [0, 0, 0, 0, 0]
};
constructor(props) {
super(props);
this.player = [];
}
componentDidMount() {
this.progress_state();
this.duration_state();
this.video_pause_state(false);
}
play_pause_button = (index) => {
if (this.state.progress >= 1) {
this.player[index].seek(0);
}
var statevisible = this.state.video;
statevisible[index] = !statevisible[index];
this.setState({
video: statevisible
});
this.forceUpdate();
};
progress_bar_touch(e, index) {
const position = e.nativeEvent.locationX;
const progress = (position / 250) * this.state.duration[index];
this.player[index].seek(progress);
};
handleProgress(progress, index) {
var statevisible = this.state.progress;
statevisible[index] = progress.currentTime / this.state.duration[index];
this.setState({
progress: statevisible
});
this.forceUpdate();
};
handleLoad(meta, index) {
var statevisible = this.state.duration;
statevisible[index] = meta.duration;
this.setState({
duration: statevisible
});
this.forceUpdate();
};
onViewableItemsChanged = async ({ viewableItems }) => {
this.video_pause_state(true);
if (viewableItems != '' && viewableItems != null) {
var indexvalue = viewableItems[0]['index'];
var statevisible = this.state.video;
statevisible[indexvalue] = !statevisible[indexvalue];
this.setState({
video: statevisible
});
this.forceUpdate();
}
}
// shouldComponentUpdate() {
// return false
// }
video_pause_state(value) {
var statevisible = [];
for (var i = 0; i < list.length; i++) {
statevisible[i] = value;
}
this.setState({
video: statevisible
});
}
progress_state() {
var statevisible = [];
for (var i = 0; i < list.length; i++) {
statevisible[i] = 0;
}
this.setState({
progress: statevisible
});
}
duration_state() {
var statevisible = [];
for (var i = 0; i < list.length; i++) {
statevisible[i] = 0;
}
this.setState({
duration: statevisible
});
}
video_end(index) {
var statevisible1 = this.state.duration;
statevisible1[index] = 0;
var statevisible2 = this.state.progress;
statevisible2[index] = 0;
this.setState({
duration: statevisible1,
progress: statevisible2
});
this.play_pause_button(index);
}
keyExtractor = (item, index) => index.toString()
renderItem = ({ item, index }) => (
<>
{item.type != 'YouTube' ?
<>
<View style={styles.container}>
<View>
<Video
paused={this.state.video[index]}
muted={this.state.video[index]}
source={LightVideo}
// controls={true}
// repeat={true}
style={styles.videos}
resizeMode="cover"
onLoad={(meta) => this.handleLoad(meta, index)}
onProgress={(progress) => this.handleProgress(progress, index)}
onEnd={() => this.video_end(index)}
ref={(ref) => {
this.player[index] = ref
}}
/>
<View style={styles.controls}>
<TouchableWithoutFeedback onPress={(event) => this.play_pause_button(index)}>
<Icon name={!this.state.video[index] ? "pause" : "play"} size={30} color="#FFF" />
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={(event) => this.progress_bar_touch(event, index, this)}>
<View>
<ProgressBar
progress={this.state.progress[index]}
color="#FFF"
unfilledColor="rgba(255,255,255,.5)"
borderColor="#FFF"
width={230}
height={20}
/>
</View>
</TouchableWithoutFeedback>
<Text style={styles.duration}>
{secondsToTime(Math.floor(this.state.progress[index] * this.state.duration[index]))}
</Text>
</View>
</View>
</View>
</>
:
<>
<View style={{ marginTop: 50 }}>
<YouTube
apiKey="YOUR_API_KEY"
videoId="YOUR_YOUTUBE_VIDEO_ID_FROM_URL"
play={this.state.video[index]}
style={styles.videos}
/>
</View>
</>
}
</>
)
render() {
return (
<>
<SafeAreaView style={{ flex: 1 }}>
<FlatList
keyExtractor={this.keyExtractor}
data={list}
renderItem={this.renderItem}
extraData={this.state}
onViewableItemsChanged={this.onViewableItemsChanged}
removeClippedSubviews={true}
maxToRenderPerBatch={3}
initialNumToRender={3}
legacyImplementation={true}
/>
</SafeAreaView>
</>
);
}
}
const wid = "95%";
const styles = StyleSheet.create({
container: {
flex: 1,
marginBottom: 60,
marginTop: 60,
},
controls: {
backgroundColor: "rgba(0, 0, 0, 0.5)",
height: 48,
left: 0,
bottom: 0,
right: 0,
position: "absolute",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
width: wid,
margin: 8,
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
paddingHorizontal: 10,
},
mainButton: {
marginRight: 15,
},
duration: {
color: "#FFF",
marginLeft: 15,
},
videos: {
width: wid,
backgroundColor: '#ccc',
borderRadius: 10,
overflow: 'hidden',
margin: 8,
height
},
});
Update
I have come up with this final solution. But not able to do autoplay. Need ideas on this.
import React from 'react';
import { View, StyleSheet, SafeAreaView } from 'react-native';
import YouTube from 'react-native-youtube';
import { OptimizedFlatList } from 'react-native-optimized-flatlist'
import VideoPlayer from 'react-native-video-player';
const list = [
{
'type': 'Normal'
},
{
'type': 'YouTube'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
{
'type': 'YouTube'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
];
export default class App extends React.PureComponent {
constructor() {
super();
this.player = [];
this.state = {
video: { width: undefined, height: undefined, duration: undefined },
thumbnailUrl: undefined,
videoUrl: undefined,
};
}
keyExtractor = (item, index) => index.toString()
renderItem = ({ item, index }) => (
<>
{item.type != 'YouTube' ?
<>
<View style={styles.videos}>
<VideoPlayer
// autoplay
// pauseOnPress
video={{ uri: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', type: 'mp4' }}
resizeMode={'cover'}
ref={r => this.player[index] = r}
/>
</View>
</>
:
<>
<View style={{ marginTop: 50 }}>
<YouTube
apiKey="YOUR_API_KEY"
videoId="3NQRhE772b0"
style={{...styles.videos,...styles.videos1}}
/>
</View>
</>
}
</>
)
onViewableItemsChanged = async ({ viewableItems }) => {
if (viewableItems != '' && viewableItems != null) {
var indexvalue = viewableItems[0]['index'];
indexvalue++;
if (indexvalue != 1) {
if (!this.player[indexvalue].state.isPlaying) {
this.player[indexvalue].pause();
} else {
this.player[indexvalue].resume();
}
}
}
}
render() {
return (
<>
<SafeAreaView style={{ flex: 1 }}>
<OptimizedFlatList
keyExtractor={this.keyExtractor}
data={list}
renderItem={this.renderItem}
removeClippedSubviews={true}
onViewableItemsChanged={this.onViewableItemsChanged}
/>
</SafeAreaView>
</>
);
}
}
const styles = StyleSheet.create({
videos: {
width: "95%",
backgroundColor: '#ccc',
borderRadius: 10,
overflow: 'hidden',
margin: 10,
marginBottom: 20,
marginTop: 20
},
videos1: {
height: 250
}
});
I need to change the selectedDay to the current day every time the user navigates to the calendar screen.
I set the selected date as today and can already detect when the user acesses the screen, but even when I change the state or force update, the calendar doesn't move to the date I set as selected.
componentDidUpdate = async (prevProps) => {
if (prevProps.isFocused !== this.props.isFocused && this.props.isFocused) {
this.forceUpdate()
}
}
and
<Agenda
items={events}
pastScrollRange={50}
futureScrollRange={50}
onDayPress={this.setCurrentDate}
loadItemsForMonth={this.loadItems}
renderItem={this.renderItem}
renderEmptyDate={this.renderEmptyDate}
rowHasChanged={this.rowHasChanged}
selected={this.state.today}
/>
With forceUpdate or changing some arbitrary state, the calendar stays in the currently selected date. I wanted it to go back to today.
You can set the ref for Agenda component
ref={ref => {
this.agenda = ref;
}}
Then on componentDidUpdate, change date to current date by calling function onDayChange of Agenda component
if (prevProps.isFocused !== this.props.isFocused) {
setTimeout(() => {
this.agenda.onDayChange(this.state.today);
}, 500);
Complete Code
import React, { Component } from "react";
import { Agenda } from "react-native-calendars";
import { Text, View, StyleSheet } from "react-native";
import { withNavigationFocus } from "react-navigation";
class Home extends Component {
constructor(props) {
super(props);
this.state = {
items: {},
today: new Date().toISOString().split("T")[0]
};
}
componentDidUpdate(prevProps) {
if (prevProps.isFocused !== this.props.isFocused) {
setTimeout(() => {
this.agenda.onDayChange(this.state.today);
}, 500);
}
}
render() {
return (
<View style={{ flex: 1 }}>
<Text
style={{ padding: 30, fontWeight: "bold", textAlign: "center" }}
onPress={() => this.props.navigation.navigate("NewScreen")}
>
Go To Next Screen
</Text>
<Agenda
items={this.state.items}
loadItemsForMonth={this.loadItems.bind(this)}
selected={this.state.today}
renderItem={this.renderItem.bind(this)}
renderEmptyDate={this.renderEmptyDate.bind(this)}
rowHasChanged={this.rowHasChanged.bind(this)}
onDayPress={day => {
console.log("selected day", day);
}}
ref={ref => {
this.agenda = ref;
}}
/>
</View>
);
}
loadItems(day) {
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = this.timeToString(time);
if (!this.state.items[strTime]) {
this.state.items[strTime] = [];
const numItems = Math.floor(Math.random() * 5);
for (let j = 0; j < numItems; j++) {
this.state.items[strTime].push({
name: "Item for " + strTime,
height: Math.max(50, Math.floor(Math.random() * 150))
});
}
}
}
//console.log(this.state.items);
const newItems = {};
Object.keys(this.state.items).forEach(key => {
newItems[key] = this.state.items[key];
});
this.setState({
items: newItems
});
}, 1000);
// console.log(`Load Items for ${day.year}-${day.month}`);
}
renderItem(item) {
return (
<View style={[styles.item, { height: item.height }]}>
<Text>{item.name}</Text>
</View>
);
}
renderEmptyDate() {
return (
<View style={styles.emptyDate}>
<Text>This is empty date!</Text>
</View>
);
}
rowHasChanged(r1, r2) {
return r1.name !== r2.name;
}
timeToString(time) {
const date = new Date(time);
return date.toISOString().split("T")[0];
}
}
const styles = StyleSheet.create({
item: {
backgroundColor: "white",
flex: 1,
borderRadius: 5,
padding: 10,
marginRight: 10,
marginTop: 17
},
emptyDate: {
height: 15,
flex: 1,
paddingTop: 30
}
});
export default withNavigationFocus(Home);
native i'm trying to swipe to delete a Rdvdetail ( second code )
but when i delete it ,it doesn't disappear from scrollView i have to reopen the page to make it disappear but backside
it works perfectly well i don't how it gonna works to make it disappear
is there any way i could make it disappear immediately from the scrollView ?
by auto reloading the scrollview or filer any help ?
import React, { Component } from "react";
import { ScrollView } from "react-native";
import axios from "axios";
import RdvDetail from "./RdvDetail";
import { CardSection } from "./utilities/CardSection";
import { Spinner } from "./utilities/Spinner";
import Swipeout from "react-native-swipeout";
class Event extends Component {
constructor(props) {
super(props);
this.state = {
Rdvs: [],
rowIndex: null,
refreshing: false
};
}
componentWillMount() {
this.fetchdata();
}
getInitialState = () => {
return {
scrollEnabled: true
};
};
_allowScroll = scrollEnabled => {
this.setState({ scrollEnabled: scrollEnabled });
};
fetchdata = () => {
axios
.get("http://localhost:3000/api/5cc92f1b8929820fecdecda3/mesRdv")
.then(response => this.setState({ Rdvs: response.data }));
};
deleteRdv = id_rdv => {
axios
.delete("http://localhost:3000/api/rdv/" + id_rdv)
.then(response => {
if (response.status === 200) {
console.log(response.data);
}
})
.catch(error => {
console.log(error.response.data.message);
if (error.response.status === 400) {
}
});
};
renderRDV() {
if (this.state.Rdvs.length < 1) {
console.log("here");
return (
<CardSection>
<Spinner size="large" />
</CardSection>
);
} else {
return this.state.Rdvs.map(Rdv => (
<Swipeout
right={[
{
text: "Delete",
backgroundColor: "red",
color: "white",
onPress: () => this.deleteRdv(Rdv._id),
autoClose: true
}
]}
rowIndex={Rdv._id}
sectionId={0}
autoClose={true}
key={Rdv._id}
scroll={event => this._allowScroll(event)}
>
<RdvDetail key={Rdv._id} Rdv={Rdv} />
</Swipeout>
));
}
}
render() {
return (
<ScrollView scrollEnabled={this.state.scrollEnabled}>
{this.renderRDV()}
</ScrollView>
);
}
}
export default Event;
import React, { Component } from "react";
import { Text, View, StyleSheet, TouchableOpacity } from "react-native";
const AlbumDetail = props => {
state = {
rowIndex: null,
monthNames: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
]
};
return (
<View style={styles.container}>
<View style={styles.eventBox}>
<View style={styles.eventDate}>
<Text style={styles.eventDay}>{props.Rdv.day + " "}</Text>
<Text style={styles.eventMonth}>
{this.state.monthNames[props.Rdv.month - 1]}
</Text>
</View>
<View style={styles.eventContent}>
<Text style={styles.eventTime}>{props.Rdv.time}</Text>
<Text style={styles.userName}>{props.Rdv.doctor}</Text>
<Text style={styles.description}>Rdv note</Text>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: "#DCDCDC"
},
eventList: {
marginTop: 20
},
eventBox: {
padding: 10,
marginTop: 5,
marginBottom: 5,
flexDirection: "row"
},
eventDate: {
flexDirection: "column"
},
eventDay: {
fontSize: 30,
color: "#0099FF",
fontWeight: "600"
},
eventMonth: {
fontSize: 16,
color: "#0099FF",
fontWeight: "600"
},
eventContent: {
flex: 1,
flexDirection: "column",
alignItems: "flex-start",
marginLeft: 10,
backgroundColor: "#FFFFFF",
padding: 10,
borderRadius: 10
},
description: {
fontSize: 15,
color: "#646464"
},
eventTime: {
fontSize: 18,
color: "#151515"
},
userName: {
fontSize: 16,
color: "#151515"
},
test: {
borderRadius: 20
}
});
export default AlbumDetail;
You could update the Rdvs list in your state state after each delete which would cause the list to re-render. Like this:
deleteRdv = id_rdv => {
axios
.delete("http://localhost:3000/api/rdv/" + id_rdv)
.then(response => {
if (response.status === 200) {
console.log(response.data);
}
this.fetchdata(); // Add this line to fetch new list
})
.catch(error => {
console.log(error.response.data.message);
if (error.response.status === 400) {
}
});
};