I have a list of Views , and each view contain delete button.
I want to start scale out animation only on pressed view.
For now, with the next code , when I press on delete button, all views in this list are animated.
Here is my functional component :
export const SubTasksView = ({subTasks, onAddSubTask, subTaskValue, setSubTaskValue, onPressDeleteSubTask}) => {
const removeAnim = new Animated.Value(1);
const startRemoveAnimation = () => {
Animated.timing(
removeAnim,
{
toValue: 0,
duration: 300,
useNativeDriver: true
}
).start();
};
const onPressDeleteSubTaskHandler = index => {
startRemoveAnimation();
setTimeout(() => {
onPressDeleteSubTask(index);
}, 300);
};
return (
<View style={styles.mainContainer}>
<View style={styles.textInputContainerStyle}>
<TextInput
style={styles.textInputStyle}
placeholder={strings.PLACEHOLDER_SUB_TASK}
value={subTaskValue}
onChangeText={setSubTaskValue}
/>
<TouchableOpacity style={styles.addButtonStyle} onPress={onAddSubTask}>
<Ionicons name={icons.ICON_ADD} size={35} color={color.ORANGE}/>
</TouchableOpacity>
</View>
{subTasks.map((subTask, index) => {
return (
<Animated.View key={subTask + 'd' + index}
style={[styles.subTasksContainer,
{
transform: [
{scale: removeAnim}
]
}
]}>
<Text style={styles.subTaskText}>{subTask}</Text>
<TouchableOpacity onPress={() => {
onPressDeleteSubTaskHandler(index)
}}>
<Ionicons name={icons.ICON_TRASH} size={20} color={color.DARK_GREY}/>
</TouchableOpacity>
</Animated.View>
);
})}
</View>
);
};
Ok I fixed it within next way:
Just created new component and rendered it with FlatList
export const SubTaskItem = ({subTask, renderedIndex, onPressDeleteButton}) => {
const removeAnim = new Animated.Value(1);
const onDeletePressHandler = () => {
Animated.timing(
removeAnim,
{
toValue: 0,
duration: 100,
useNativeDriver: true
}
).start(() => {
onPressDeleteButton(renderedIndex)
});
};
return(
<Animated.View style={[styles.subTasksContainer,
{
transform: [
{scale: removeAnim}
]
}]}>
<Text style={styles.subTaskText}>{subTask}</Text>
<TouchableOpacity onPress={() => onDeletePressHandler()} >
<Ionicons name={icons.ICON_TRASH} size={20} color={color.DARK_GREY}/>
</TouchableOpacity>
</Animated.View>
)
};
Related
I'm trying to delete selected image from an array of images and yet only the first image on the list gets deleted whenever i tap any other image to delete. This is surprising cause i implemented the same method when generating a list in the same screen and it deletes the correct list item each time i tap on it to delete.
Here is all the code in the file excluding cascading styles. Its a lot but i Hope this helps.
const AddPost = () => {
const navigation = useNavigation();
// Thumbnail State
const [thumbnail, setThumbnail] = useState(null);
// Media State
const [media, setMedia] = useState([]);
// Details State
const [title, setTitle] = useState('');
const [category, setCategory] = useState('');
const [caption, setCaption] = useState('');
const [price, setPrice] = useState('');
const [details, setDetails] = useState(false);
// Store State
const [itemName, setItemName] = useState('');
const [itemPrice, setItemPrice] = useState('');
const [photoArray, setPhotoArray] = useState([]);
const [storeItems, setStoreItems] = useState([]);
const width = useWindowDimensions().width;
const numColumns = Math.ceil(width / 120);
const pickThumbnail = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
quality: 0.5,
});
if (!result.cancelled) {
setThumbnail(result.uri);
}
};
const pickMedia = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
quality: 0.2,
});
if (!result.cancelled) {
setMedia([...media, result.uri]);
}
};
const deleteMedia = (index) => {
let removeMedia = [...media];
removeMedia.splice(index, 1);
setMedia(removeMedia)
console.log(index)
};
const addDetailItem = () => {
if (title == '' || category == '' || caption == '' || price == '') {
Alert.alert('Error', 'Please fill in the item detail.')
} else {
Keyboard.dismiss();
setDetails(true);
detailsRef?.current?.close();
};
};
const detailsRef = useRef(null);
const toggleModal = () => {
detailsRef?.current?.present();
}
const toggleModalClose = () => {
detailsRef?.current?.close();
}
const addItem = {
id: Math.floor(Math.random() * 11),
itemName: itemName,
itemPrice: itemPrice,
photo: photoArray
};
const storeRef = useRef(null);
const toggleStoreModal = () => {
storeRef?.current?.present();
}
const toggleStoreModalClose = () => {
storeRef?.current?.close();
}
const addStoreItem = () => {
if (itemName == '' || itemPrice == '') {
Alert.alert('Error', 'Please fill in the item detail.')
} else {
Keyboard.dismiss();
setStoreItems([...storeItems, addItem]);
setItemName(null);
setItemPrice(null);
setPhotoArray([]);
};
};
const deleteItem = (index) => {
let removeItem = [...storeItems];
removeItem.splice(index, 1);
setStoreItems(removeItem)
};
const pickPhoto = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
quality: 0.2,
});
if (!result.cancelled) {
setPhotoArray([...photoArray, result.uri]);
}
};
const deletePhoto = (index) => {
let removeItem = [...photoArray];
removeItem.splice(index, 1);
setPhotoArray(removeItem)
};
const store = () => {
setStoreItems([...storeItems]);
storeRef?.current?.close();
Keyboard.dismiss();
};
return (
<View style={styles.container}>
{/* Header */}
<Header
title={'Add Post'}
leftComponent={
<View style={styles.headerLeft}>
<Image source={images.logo} style={{ height: 28, width: 28, tintColor: COLORS.primary2}} />
</View>
}
rightComponent={
<TouchableOpacity
style={{
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
}}
onPress= {() => console.log('Post Sumbitted') }
>
<Image
source={icons.post2}
style={{
width: 35,
height: 35,
tintColor: COLORS.primary2,
}}
/>
</TouchableOpacity>
}
/>
<View style={styles.subContainer}>
<ScrollView>
<Text style={styles.textDetail}>Add a photo or video post with thumbnail, category, caption, price, and store details (Optional).</Text>
{/* Add Thumbnail */}
<AddPostItem label={'Thumbnail'} onPress={pickThumbnail}/>
{thumbnail &&
<View style={styles.thumbnail}>
<Image source={{ uri: thumbnail }} style={styles.thumbnailPhoto} />
</View>
}
{/* Add Media */}
<AddPostItem label={'Media (Video/Photo)'} onPress={pickMedia} />
<View style={{flexDirection: 'row'}}>
{Array.from(Array(numColumns)).map((col, colIndex) => (
<View style={{flex: 1}} key={colIndex}>
{media
.filter((item, index) => index % numColumns === colIndex)
.map((item, index) => (
<View key={index.toString()} style={styles.mediaContainer} >
<Image source={{uri: item}} style={styles.addedMedia}/>
<TouchableOpacity style={styles.imageCancel} key={index} onPress={() => deleteMedia(index)}>
<Image source={icons.cross} style={styles.imageCancelIcon}/>
</TouchableOpacity>
</View>
))}
</View>
))
}
</View>
{/* Add Details */}
<AddPostItem label={'Details (Title, Caption, etc)'} onPress={toggleModal}/>
{details &&
<View style={{marginHorizontal: 20}}>
<View style={{flexDirection: 'row', }}>
<Text style={{color: COLORS.primary2, ...FONTS.body4}}>Title: </Text>
<Text style={{color: COLORS.white, ...FONTS.body4}}>{title}</Text>
</View>
<View style={{flexDirection: 'row', marginTop: 5,}}>
<Text style={{color: COLORS.primary2, ...FONTS.body4}}>Category: </Text>
<Text style={{color: COLORS.white, ...FONTS.body4}}>{category}</Text>
</View>
<View style={{flexDirection: 'row', marginTop: 5,}}>
<Text style={{color: COLORS.primary2, ...FONTS.body4}}>Price: </Text>
<Text style={{color: COLORS.white, ...FONTS.body4}}>N{price}</Text>
</View>
<View style={{marginTop: 5,}}>
<Text style={{color: COLORS.primary2, ...FONTS.body4}}>Caption: </Text>
<Text style={{color: COLORS.white, ...FONTS.body4}}>{caption}</Text>
</View>
</View>
}
{/* Add Store */}
<AddPostItem label={'Store Items (Optional)'} onPress={toggleStoreModal}/>
{storeItems.map((item, index) => {
return (
<View key={index.toString()} style={styles.itemContainer}>
<Text style={styles.itemName}>{item?.itemName}</Text>
<Text style={styles.itemPrice}>N{item?.itemPrice}</Text>
</View>
)
})
}
<View>
</View>
</ScrollView>
</View>
<BottomSheetModal
enablePanDownToClose={true}
ref={detailsRef}
snapPoints={['100%']}
index={0}
backgroundComponent={
({style}) =>
<View style={[style, {
backgroundColor: COLORS.primary,
borderRadius: 30,
}]}/>}
>
{/* Post Details */}
{/* Header */}
<ModalHeader left={toggleModalClose} right={addDetailItem} />
<View style={{flex: 1, backgroundColor: COLORS.primary3, borderTopRightRadius: 35, borderTopLeftRadius: 35}}>
<View style={styles.addDetailText}>
<Text style={styles.textHeader}>Add details</Text>
<Text style={styles.textBody}>Provide the necessary details for your post.</Text>
</View>
<View style={{paddingHorizontal: 10}}>
<FormInput
autoCapitalize='words'
placeholder={'Give it a title'}
onChange={setTitle}
value={title}
/>
<FormInput
autoCapitalize='words'
placeholder={'Category'}
onChange={setCategory}
value={category}
/>
<FormMultiText
autoCapitalize='sentences'
placeholder={'Caption'}
onChange={setCaption}
multiline={true}
numberOfLines={4}
value={caption}
/>
<FormInput
keyboardType='number-pad'
placeholder={'Price (Optional)'}
onChange={setPrice}
value={price}
/>
</View>
<Text style={{color: COLORS.gray, ...FONTS.body5, paddingHorizontal: 10, marginTop: 5, marginLeft: 65}}>Leave this input empty for a "FREE POST".</Text>
</View>
</BottomSheetModal>
<BottomSheetModal
enablePanDownToClose={false}
ref={storeRef}
snapPoints={['100%']}
index={0}
backgroundComponent={
({style}) =>
<View style={[style, {
backgroundColor: COLORS.primary,
borderRadius: 30,
}]}/>}
>
<ModalHeader left={toggleStoreModalClose} right={store} />
<View style={styles.storeItemConatainer}>
<View style={{flex: 1, backgroundColor: COLORS.primary3, borderTopRightRadius: 35, borderTopLeftRadius: 35}}>
<View >
<View style={styles.titleBar}>
<Text style={styles.textHeader}>Add store items (Optional)</Text>
</View>
<Text style={styles.textBody}>Include items available for purchase and their item price. You can add more than one item and multiple photo(s) to each item.</Text>
</View>
{/* Store Items */}
<TouchableOpacity onPress={pickPhoto} style={styles.addPhotoBtn}>
<Text style={{color: COLORS.primary, textAlign: 'center', ...FONTS.body3}}>Add Photo(s)</Text>
</TouchableOpacity>
{/* Photo Container */}
<View style={{flexDirection: 'row'}}>
{Array.from(Array(numColumns)).map((col, colIndex) => (
<View style={{flex: 1}} key={colIndex}>
{photoArray
.filter((item, index) => index % numColumns === colIndex)
.map((item, index) => (
<View key={index.toString()} style={styles.photoContainer}>
<Image source={{uri: item}} style={styles.addedPhoto}/>
<TouchableOpacity style={styles.photoCancel} onPress={() => deletePhoto(index)}>
<Image source={icons.cross} style={styles.photoCancelIcon}/>
</TouchableOpacity>
</View>
))}
</View>
))
}
</View>
<View style={styles.storeInput}>
<TouchableOpacity onPress={addStoreItem}>
<View style={styles.iconContainer}>
<Image source={icons.add} style={styles.icon}/>
</View>
</TouchableOpacity>
<View >
<FormStoreInput
autoCapitalize='words'
placeholder={'Item Name'}
onChange={setItemName}
value={itemName}
/>
<FormStoreInput
keyboardType='number-pad'
placeholder={'Item Price'}
onChange={setItemPrice}
value={itemPrice}
/>
</View>
</View>
<BottomSheetScrollView>
{storeItems.map((item, index) => {
return (
<View key={index.toString()} style={{flexDirection: 'row', marginBottom: 10, marginTop: 5}}>
<AddStoreItem items={item}/>
<TouchableOpacity style={styles.cancel} key={index} onPress={() => deleteItem(index)}>
<Image source={icons.cross} style={styles.cancelIcon}/>
</TouchableOpacity>
</View>
)
})
}
</BottomSheetScrollView>
</View>
</View>
</BottomSheetModal>
</View>
)
}
export default AddPost
This post has been updated.
I guess since we are dealing with images and not an object array that's why index wasnt working. So i changed index with items and decided to us the .filter method instead of .splice. And it worked.
const deleteMedia = (item) => {
setMedia((prev) => prev.filter((el) => el !== item));
console.log(item)
};
You need to declare remove media outside the function delete media because everytime you call delete media. You are reinitalizing the removeMedia useState to the original media values. I did not test these codes, but from the codes I can clearly tell that you are just reinitalizing remove media back to its original value. Try this
let removeMedia=[...media];
const deleteMedia = (index) => {
removeMedia.splice(index, 1);
setMedia(removeMedia)
};
I have a modal component that I want to reuse in future component.
For this reason I want to have it in its own file.
I don't manage to call the component inside the other properly though.
Here is my last attempt of it.
The Modal component code:
export const FlyingDescription = (cityDescription) => {
const [modalVisible, setModalVisible] = useState(false);
return (
<View>
<Modal
animation="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => setModalVisible(!modalVisible)}
>
<View style={styleBoxParent}>
<View style={styleBoxChildren}>
<LinearGradient
style={styleLinearGradient}
colors={['#136a8a', '#267871']}
start={[0, 0.65]}
>
<Text style={styleText}>{cityDescription}</Text>
<Pressable
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styleText}>Close</Text>
</Pressable>
</LinearGradient>
</View>
</View>
</Modal>
</View>
);
};
The component where I want to call the Modal component:
import FlyingDescription from './FlyingDescription.js';
var utils = require('./utils');
export default class SearchScreen extends React.Component {
constructor(props) {
super(props);
this.navigation = props.navigation;
this.state = {
searchInput: '',
item : {},
renderSearch: false,
renderFlyingDescription: false,
};
this.errorMessage = 'Search for cities...';
}
resetState = () => {
this.setState({
item: {},
renderable: false,
}); }
setSearchInput = (value) => {
this.setState({
searchInput: value
});
}
searchCity = () => {
this.resetState();
utils.fetchWeather(this.state.searchInput).then(response => {
if (response.cod == 200) {
console.log(response);
this.setItemState(
{
name: response.name,
temp: Math.ceil(response.main.temp),
type: response.weather[0].main,
desc: 'Humidity: ' + response.main.humidity + '% - ' + response.weather[0].main
}
);
this.setRenderSearch();
}
});
}
setItemState = (newItem) => {
this.setState(
{
item: newItem,
}
);
}
setRenderSearch = () => {
this.setState(
{
renderSearch: true,
}
);
}
render = () => {
return(
<View style={utils.style.container}>
<StatusBar barStyle="light-content" />
<Text style={utils.style.titleContainer}>☀️ CityWeather</Text>
<View style={{alignItems: 'center', width:'90%'}}>
<Text>Search for a city</Text>
<TextInput
onChangeText={(value) => this.setSearchInput(value)}
value={this.searchInput}
style={{ width: '80%', padding: 15, margin: 5, backgroundColor: 'black', color: 'white' }}
/>
<TouchableHighlight
style={{backgroundColor: 'grey', padding: 20, borderRadius: 8}}
onPress={this.searchCity}
>
<Text style={{fontSize: 14, color:'white'}}>Search</Text>
</TouchableHighlight>
</View>
{ this.state.renderSearch ? (
<TouchableHighlight
underlayColor="white"
onPress={ () => this.setState({renderFlyingDescription: true})}
>
<LinearGradient
colors={['rgba(0,0,0,0.05)', 'rgba(0,0,0,0)']}
start={[0, 0.5]}
>
<View style={utils.style.row}>
<Text style={[utils.getTempRange(this.state.item.temp), utils.style.temp]}>
{utils.getEmoji(this.state.item.type)} {this.state.item.temp} °C
</Text>
<Text style={utils.style.cityName}>{this.state.item.name}</Text>
</View>
</LinearGradient>
</TouchableHighlight>
) : (
// WHERE I WANT TO RENDER MY MODAL COMPONENT
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center', fontSize: 32}}>
<Text>{this.errorMessage}</Text>
</View>
)
}
{
renderFlyingDescription(this.state.renderFlyingDescription, this.state.item.desc)
}
</View>
);
}
}
export function renderFlyingDescription(isInterpretable, cityDescription) {
if(isInterpretable) {
return <FlyingDescription cityDescription={cityDescription} />
}
}
I'm trying to implement react-navigation-shared-elements with react-navigation v4, but somthing wrong with the way I'm trying.
I have Screen , that contain component ( SectionList) that rendering and other component ( TaskCard ) that contain the wanted shared element.
I've tried to implement this according to the documentation, but it's not working.
Please see the code:
My Router:
const HomeStack = createSharedElementStackNavigator({
HomeScreen,
TaskDetailsScreen,
EditTaskScreen,
}, {
defaultNavigationOptions: headerDefaultOption,
});
const AppNavigator = createSwitchNavigator(
{
SplashScreen,
AuthStack,
HomeStack,
}
);
HomeScreen that contain the SectionList component:
export const HomeScreen = ({navigation}) => {
const onTaskPressHandler = (task) => {
navigation.push(screens.TASK_DETAILS_SCREEN, {task});
};
return (
<View style={styles.container}>
<TaskList data={tasks} onTaskPress={onTaskPressHandler} onTaskLongPress={openQuickActionsWithData}/>
</View>
);
};
TaskList:
export const TaskList = ({data, onTaskPress, onTaskLongPress}) => {
data.sort((a, b) => (a.taskEndDate > b.taskEndDate) ? 1 : ((b.taskEndDate > a.taskEndDate) ? -1 : 0));
return (
<SectionList
showsVerticalScrollIndicator={false}
sections={sortedData}
keyExtractor={(item, index) => item + index}
renderItem={({item, index}) => {
return (
<TaskCard data={item} index={index} onTaskPress={onTaskPress} onTaskLongPress={onTaskLongPress}/>
);
}}
renderSectionHeader={({section: {title}, section: {data}}) => {
return (
renderTitleIfHasData(data, title)
);
}}
/>
);
};
TaskCard with shared element :
import {SharedElement} from 'react-native-shared-element';
export const TaskCard = ({data, index, onTaskPress, onTaskLongPress}) => {
const onPressHandler = data => {
onTaskPress(data)
};
return (
<Animated.View rkey={index} style={[styles.mainContainer, {transform: [{scale: scaleAnim}]}]}>
<TouchableOpacity
index={index}
activeOpacity={layout.activeOpacity}
style={[styles.taskContainer, {backgroundColor: isFinished ? color.ORANGE : color.GREY,}, renderBorderRadiusPosition()]}
onPress={() => onPressHandler(data)}
onLongPress={() => onTaskLongPress(data)}>
<View style={styles.titleContainer}>
<SharedElement id={`data.${data.taskCreationDate}.sharedTask`}>
<View style={styles.taskImageTypeContainer}>
<Image source={getTaskImageByType(data.taskType)} style={styles.typeImageStyle}/>
</View>
</SharedElement>
</TouchableOpacity>
</Animated.View>
);
};
Details screen with same shared element :
export const TaskDetailsScreen = ({navigation}) => {
return (
<ScrollView style={styles.mainContainer}>
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<SharedElement id={`data.${task.taskCreationDate}.sharedTask`}>
<View style={styles.taskTypeContainer}>
<Image source={getTaskImageByType(task.taskType)} style={styles.taskTypeImage}/>
</View>
</SharedElement>
</View>
</ScrollView>
);
};
TaskDetailsScreen.sharedElements = (navigation, otherNavigation, showing) => {
const task = navigation.getParam('task');
return [{
id: `data.${task.taskCreationDate}.sharedTask`,
animation: 'move',
resize: 'clip'
}];
};
So I want to create a beautiful UI of Camera Roll that has a borderColor instead of margin or padding because it will make the images do not fit on the width of the screen. I do not want to add borderColor to the right and left the side of the images too. It just likes on Instagram.
This is what I want to achieve:
Here are my codes:
CameraRoll.js
setIndex = (index) => {
if (index === this.state.index) {
index = null
}
this.setState({ index });
};
getPhotos = () => {
CameraRoll.getPhotos({
first: 200,
assetType: 'All'
})
.then(res => {
this.setState({
photos: res.edges,
});
})
.catch((err) => {
console.log('Error image: ' + err);
});
};
render() {
return(
<View style={styles.container}>
<Image
source={{uri: this.state.pickedImage}}
style={styles.image}
/>
<ScrollView contentContainerStyle={styles.scrollView} showsVerticalScrollIndicator={false}>
{this.state.photos.map((photos, index) => {
return(
<TouchableHighlight
style={{opacity: index === this.state.index ? .5 : 1}}
onPress={() => this.setState({pickedImage: photos.node.image.uri})}
key={index}
underlayColor='transparent'
>
<Image
style={[{width: width / 3, height: width /3}]}
source={{uri: photos.node.image.uri}}
resizeMode='cover'
/>
</TouchableHighlight>
);
})}
</ScrollView>
</View>
);
}
}
Change style of TouchableHighlight or Image, adding borderColor:"red", borderWidth:10
setIndex = (index) => {
if (index === this.state.index) {
index = null
}
this.setState({ index });
};
getPhotos = () => {
CameraRoll.getPhotos({
first: 200,
assetType: 'All'
})
.then(res => {
this.setState({
photos: res.edges,
});
})
.catch((err) => {
console.log('Error image: ' + err);
});
};
render() {
return(
<View style={styles.container}>
<Image
source={{uri: this.state.pickedImage}}
style={styles.image}
/>
<ScrollView contentContainerStyle={styles.scrollView} showsVerticalScrollIndicator={false}>
{this.state.photos.map((photos, index) => {
return(
<TouchableHighlight
style={{
opacity: index === this.state.index ? .5 : 1,
borderColor:"red", borderWidth:10
}}
onPress={() => this.setState({pickedImage: photos.node.image.uri})}
key={index}
underlayColor='transparent'
>
<Image
style={[{width: width / 3, height: width /3}]}
source={{uri: photos.node.image.uri}}
resizeMode='cover'
/>
</TouchableHighlight>
);
})}
</ScrollView>
</View>
);
}
}
I am using RN for the development of an application, one of the components is a list of data, I perform the integration of a flat list to form the list...
<FlatList data={this.state.tickets}
keyExtractor={(item,index) => item._id + Math.random()}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.5}
ListFooterComponent={this.footerList}
renderItem={({item}) =>
<View style={styles.childOneFlat}>
<View style={styles.childTwoFlat}>
<TouchableOpacity style={styles.childThreeFlat}
onPress={() => {this.goToTask(item)}}>
<View style={styles.childFourFlat}>
<Text style={styles.childFiveFlat}>
{'Ticket N° '+item.taskId}</Text>
<Text style={styles.childSixFlat}>></Text>
</View>
</TouchableOpacity>
</View>
</View>}>
</FlatList>
Sorry for the bad indentation...
my methods :
handleRefresh = () => {
this.setState({
page:1,
refreshing:true
}, () => {
this.getTickets();
});
};
handleLoadMore = () => {
this.setState((prevStates,nextProps) => ({page: prevStates + 1,
loadingMore:true}), () => {this.getTickets();});
};
renderFooter = () => {
if (!this.state.loadingMore) return null;
return (
<View
style={{
position: 'relative',
width: width,
height: height,
paddingVertical: 20,
borderTopWidth: 1,
marginTop: 10,
marginBottom: 10,
borderColor: colors.veryLightPink
}}
>
<ActivityIndicator animating size="large" color='blue'/>
</View>
);
};
handleRefresh = () => {
this.setState(
{
page: 1,
refreshing: true
},
() => {
this._fetchAllBeers();
}
);
};
Someone may see the error that I could not find.
I would like to be able to incorporate infinity scrolling in the list, thanks to whoever answers from now...
Did you check whether your data prop is updating? this.state.tickets should always append the next items which are received from the this.getTickets(); API call instead of rewriting the whole array.