FlatList infinity scrolling on my code is not working - javascript

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.

Related

How to animate only pressed index on array.map

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>
)
};

React Native Swipeable close after onPress not working

So I've seen many posting the same problem, but for some I don't seem to be able to adapt the posted solutions to my case.. I hope someone can tell me exactly what changes I need to do in order to get this working, since I don't know how to implement the suggested solutions!
I am using React Native Swipeable
Example of someone having the same issue
I have a file in which I built the Swipeable Component and an other class which calls the component. I've set a timeout close function on the onSwipeableOpen as a temporary solution. But ideally it should close immediately upon pressing "delete". The "..." stands for other code which I deleted since it's not important for this case.
AgendaCard.js
...
const RightActions = ({ onPress }) => {
return (
<View style={styles.rightAction}>
<TouchableWithoutFeedback onPress={onPress}>
<View style={{ flexDirection: "row", alignSelf: "flex-end" }}>
<Text style={styles.actionText}>Löschen</Text>
<View style={{ margin: 5 }} />
<MaterialIcons name="delete" size={30} color="white" />
</View>
</TouchableWithoutFeedback>
</View>
);
};
...
export class AgendaCardEntry extends React.Component {
updateRef = (ref) => {
this._swipeableRow = ref;
};
close = () => {
setTimeout(() => {
this._swipeableRow.close();
}, 2000);
};
render() {
return (
<Swipeable
ref={this.updateRef}
renderRightActions={() => (
<RightActions onPress={this.props.onRightPress} />
)}
onSwipeableOpen={this.close}
overshootRight={false}
>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.entryContainer}>
<Text style={styles.entryTitle}>{this.props.item.info}</Text>
<Text style={styles.entryTime}>
eingetragen um {this.props.item.time} Uhr
</Text>
</View>
</TouchableWithoutFeedback>
</Swipeable>
);
}
}
Agenda.js
...
renderItem(item) {
...
<AgendaCardAppointment
item={item}
onRightPress={() => firebaseDeleteItem(item)}
/>
...
}
I'm having the same issue and have been for days. I was able to hack through it, but it left me with an animation I don't like, but this is what I did anyways.
export class AgendaCardEntry extends React.Component {
let swipeableRef = null; // NEW CODE
updateRef = (ref) => {
this._swipeableRow = ref;
};
close = () => {
setTimeout(() => {
this._swipeableRow.close();
}, 2000);
};
onRightPress = (ref, item) => { // NEW CODE
ref.close()
// Delete item logic
}
render() {
return (
<Swipeable
ref={(swipe) => swipeableRef = swipe} // NEW CODE
renderRightActions={() => (
<RightActions onPress={() => this.onRightPress(swipeableRef)} /> // NEW CODE
)}
onSwipeableOpen={this.close}
overshootRight={false}
>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.entryContainer}>
<Text style={styles.entryTitle}>{this.props.item.info}</Text>
<Text style={styles.entryTime}>
eingetragen um {this.props.item.time} Uhr
</Text>
</View>
</TouchableWithoutFeedback>
</Swipeable>
);
}
}

how can i create modal page in function?

Calendar/index.js
constructor(props) {
this.state = {
CalendarModalVisible: false
};
}
toggleCalendarModal = () => {
this.setState({ CalendarModalVisible: !this.state.CalendarModalVisible });
}
setModalPage = () => {
return(
<Modal isVisible={this.state.CalendarModalVisible} onBackdropPress={() =>
{ this.toggleCalendarModal() }} >
<View style={this.style.modal_container} >
</View>
</Modal>
);
}
renderDay(day, id) {
....
return (
<TouchableOpacity onPress={() => { this.setModalPage();
this.toggleCalendarModal() }}>
<View style={[this.style.home_day, { height: days_len }]} key={day}
>
<View style={{ flex: 1, alignItems: 'center' }} key={id}>
<DayComp
...
>
{date}
</DayComp>
</View>
</View>
</TouchableOpacity>
);
renderWeek(days, id) {
const week = [];
days.forEach((day, id2) => {
week.push(this.renderDay(day, id2));
}, this);
return (<View style={[this.style.home_week} key=
{id}>{week}
</View>);
render() { ...}
return( <View
...calendar component
</View>
);
I am modifying the calendar/index.js in the react-native-calendar module.
I made the calendar page like iphone calendar.
and I want the modal page show if i click the view home_day in renderday function.....
the setModalPage function is working well, but the modal page is not showing.
how can I resolve the problem..?
Edit
I resolve the problem myself.
I added {this.forceUpdate()} in toggleCalendarModal function.

How to implement a way to delete an item from a FlatList?

I am not sure how to add a delete function in a FlatList. I know I can make different components, but I want to know how to do it within this one file. I've trying to figure this out for hours, but do not know how to do.
export default function test() {
const [enteredGoal, setEnteredGoal] = useState("");
const [courseGoals, setCourseGoals] = useState([]);
const goalInput = enteredText => {
setEnteredGoal(enteredText);
};
const addGoal = () => {
setCourseGoals(currentGoals => [
...currentGoals,
{ key: Math.random().toString(), value: enteredGoal }
]);
};
const removeGoal = goalId => {
setCourseGoals(currentGoals => {
return currentGoals.filter((goal) => goal.id !== goalId);
})
}
return (
<View style={styles.container}>
<View>
<TextInput
color="lime"
style={styles.placeholderStyle}
placeholder="Type here"
placeholderTextColor="lime"
onChangeText={goalInput}
value={enteredGoal}
/>
</View>
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={styles.listItem} >
<Text style={{ color: "lime" }}>{itemData.item.value}</Text>
</View>
)}
/>
<View>
<TouchableOpacity>
<Text style={styles.button} onPress={addGoal}>
Add
</Text>
</TouchableOpacity>
</View>
</View>
);
}
You just need to modify your code a bit to handle the delete button. Since you already have delete functionality, call that function when you click the delete button. That's it.
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={{ flexDirection: "row", justifyContent: "space-between" }}>
<Text style={{ color: "lime" }}>{itemData.item.value}</Text>
<TouchableOpacity onPress={() => removeGoal(itemData.item.key)}>
<Text>Delete</Text>
</TouchableOpacity>
</View>
)}
/>;
EDIT
change your removeGoal function as below
const removeGoal = goalId => {
setCourseGoals(courseGoals => {
return courseGoals.filter(goal => goal.key !== goalId);
});
};
Hope this helps you. Feel free for doubts.

Rendering Child Component in React Native

I am using React Native and React Navigation to build a simple app.
I have got the basic structure working with stub state but I am having problem with changing state via callback and re-render.
In my screen, I have simple start button
`<View style={styles.buttonContainer}>
<TouchableOpacity
style={[myStyles.buttonStyle, { backgroundColor: color }]}
onPress={() => handlePress(button.title)}
>
<Text style={myStyles.textStyle}>{button.title}</Text>
</TouchableOpacity>
</View>`
Problem:
After I update my parent Component state, my child component does not instantly render to match the state change. I understood React will re-render all child components when parent state is changed?
Instead, I have to move back to previous screen and navigate again to my button screen to see that the button's color and text has changed correctly.
I've read about requiring a componentWillReceiveProps(nextProps) handler but I am not sure how to use it. I put a console.log('nextProps', nextProps) inside but it does not get fired.
From navigation perspective, the Root component is on index[0] and my button view is at index[3] so it's the 3rd screen from the root.
EDIT 1: Added Code
myButton screen:
export class TeamsScreen extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.game.name}: Select Team`,
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'black',
},
headerVisible: true
})
componentWillReceiveProps(nextProps) {
console.log('nextProps', nextProps);
}
render() {
const { navigate, setParams } = this.props.navigation;
const { game, player, setGameState } = this.props.navigation.state.params;
const color = game.status === 'Start' ? 'green' : 'red';
const index = game.indexOf(player);
const status = game.status;
console.log('index', index);
console.log('status', status);
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={[myStyles.buttonStyle, { backgroundColor: color }]}
onPress={() => setGameState(index, status)}
>
<Text style={myStyles.textStyle}>{game.status}</Text>
</TouchableOpacity>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => navigate('ChangeDriverScreen', { team, game })}
title='Change Driver'
/>
</View>
<View style={{ marginTop: 40, marginBottom: 20 }}>
<Text style={{ fontSize: 16, color: 'white', alignSelf: 'center' }}>Teams</Text>
</View>
<View style={{ height: 250 }}>
<FlatList
data={player.teams}
renderItem={({item}) =>
<View style={styles.buttonContainer}>
<Button
onPress={() => navigate('TeamSelectedStartScreen', { team: item })}
title={item.name}
/>
</View>}
keyExtractor={item => item.name}
/>
</View>
<Image
style={{ alignSelf: 'center', justifyContent: 'flex-end', height: 75, width: 250, resizeMode: 'stretch'}}
source={require('./images/icons/playerPlaceholder.png')}
/>
</View>
)}}
Then the onPress function that is called back:
setGameState = (gameIndex, status) => {
console.log('setGameState', gameIndex, status);
console.log('gameStateBefore', this.state.game);
const newGameState = this.state.game.map(t => {
console.log(this.state.game.indexOf(t));
if (this.state.game.indexOf(t) === gameIndex) {
const newStatus = status === 'Start' ? 'Stop' : 'Start';
t.status = newStatus; /*eslint no-param-reassign: "off"*/
console.log('inside if', t.status);
console.log('inside if game', t);
return t;
}
return t;
});
console.log('new Game State', newGameState);
this.setState(() => ({
game: newGameState
}));
}
So the setState method works (as re-navigating back to screen 3 shows the correct state but core question is how to get immediate re-render of screen 3 when setState is called from Screen 0.

Categories