How to refresh the navigation parameters when there are more card components to navigate in React Native - react-native

When I click one card component and pass the data to the other page, and when I go back and click another one parameter that I pass from navigation, the navigate does not get changed. Here is my first page to navigate from:
import React,{ useState,useEffect} from 'react';
import { View, Text,TouchableOpacity, Button, StyleSheet ,Image,ScrollView} from 'react-native';
import { FontAwesome, Feather, MaterialIcons,Ionicons } from 'react-native-vector-icons';
const PaymentScreen = ({ route, navigation }) => {
const [paymentList, setPaymentList] = useState([]);
useEffect(() => {
fetch(
"https://run.mocky.io/v3/73958238-7761-4d81-8577-793ff92c0ea1"
)
.then((res) => res.json())
.then((data) => {
setPaymentList(data);
});
}, []);
const showPayment=() =>{
return (
paymentList &&
paymentList
.filter((word) => route.params.Name== word.userID)
.map((Aname, i) => {
return (
<View style={{padding: 8 }}>
<PaymenCard date={Aname.date} discount={Aname.id} cash={Aname.amount} forwardLink={() => navigation.navigate('morePayments',{itemId: Aname.id})}/>
</View>
);
})
)
}
return (
<View style={styles.container}>
<View style={styles.paymentbox}>
<Text style={styles.payment}>Payments</Text>
</View>
<ScrollView>
{ showPayment()}
</ScrollView>
</View>
);
};
export default PaymentScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'#22343C',
},
payment:{
fontSize:42,
color: "white",
fontWeight: "bold",
},
paymentbox:{
marginLeft:32,
paddingBottom: 5
}
});
function PaymenCard(props ){
return(
<TouchableOpacity onPress={props.forwardLink}>
<View style={styles1.cardbox}>
<View style={styles1.square}>
<View style={styles1.dollarbig}>
<MaterialIcons name="monetization-on" color="#FFC542" size={30} />
</View>
</View>
<View style={styles1.datedisc}>
<View style={styles1.date}>
<Text style={styles1.datetext}>{props.date} </Text>
</View>
<View style={styles1.discount}>
<View style={styles1.rocket}>
<FontAwesome name="rocket" color="#FFC542" size={20} />
</View>
<View style={styles1.discountval}>
<Text style={styles1.discounttext}>{props.discount}</Text>
</View>
</View>
</View>
<View style={styles1.cashbox}>
<Text style={styles1.cashtext}>{props.cash}</Text>
</View>
</View>
</TouchableOpacity>
)
}
const styles1 = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#22343C',
},
cardbox: {
height: 115,
width: 345,
backgroundColor: '#30444E',
borderRadius: 25,
marginLeft: 22,
flexDirection: 'row',
},
square: {
height: 57,
width: 59,
borderRadius: 12,
backgroundColor: '#FF565E',
marginTop: 24,
marginLeft: 23,
},
dollarbig: {
marginTop: 15,
alignItems: 'center',
},
datedisc: {
marginTop: 24,
marginLeft: 16,
width: 145,
flexDirection:"column"
},
datetext: {
color: 'white',
fontSize: 14,
},
discount:{
marginTop:15,
flexDirection:"row",
},
rocket:{
},
discountval:{
marginLeft:13
},
discounttext:{
color:"white",
fontSize: 14,
},
cashbox:{
marginTop:30,
marginLeft:25
},
cashtext:{
color:"#FF575F",
fontWeight:"bold",
fontSize:18
}
});

I found the solution. there I have used initial params. so once the value is set it not going to upgrade again. I used react context API to set the updating values globally

Related

How to send Selected Custom Checkbox data to next page in react native?

Here I have created toggle custom checkboxes and those are rendered within FlatList with Name.
Now which checkboxes are checked i want to send those names into next screen using navigation.
So how can i implement that functionality, if anyone knows then please help me for the same.
/**Code For custom checkbox:**/
import React from "react";
import {
TouchableOpacity,
Image,
View,
SafeAreaView,
Text,
} from "react-native";
import { useState } from "react";
import IconAntDesign from "react-native-vector-icons/AntDesign";
export function CheckBoxCustom() {
const [count, setCount] = useState(0);
return (
<SafeAreaView>
<TouchableOpacity
style={{
backgroundColor: "white",
width: 20,
height: 20,
borderWidth: 2,
borderColor: "#ddd",
}}
onPress={() => setCount(!count)}
>
{count ? (
<IconAntDesign name="check" size={15} color={"black"} />
) : null}
</TouchableOpacity>
</SafeAreaView>
);
}
/**Code for FlatList:**/
import React, {useState} from 'react';
import {
SafeAreaView,
Text,
View,
TouchableOpacity,
Image,
StyleSheet,
FlatList,
Dimensions,
useWindowDimensions,
ScrollView,
Button,
} from 'react-native';
import Header from '../CustomComponents/RestaurentUI/Header';
import {CheckBoxCustom} from '../CustomComponents/RestaurentUI/Checkbox';
import {TextInput} from 'react-native-gesture-handler';
import {TabView, SceneMap, TabBar} from 'react-native-tab-view';
import {NavigationContainer, useNavigation} from '#react-navigation/native';
import GetCheckBoxData from './GetCheckBoxData';
const data = [
{
name: 'Lumlère brûlée',
status: 'Problems',
},
{
name: 'Aucune eau chaude',
status: 'Problems',
},
{
name: 'Lumlère brûlée',
status: 'Problems',
},
{
name: 'Service de ménage',
status: 'Problems',
},
{
name: 'AC non-fonctionnel',
status: 'Problems',
},
{
name: 'WIFI non-fonctionnel',
status: 'Problems',
},
{
name: 'Four non-fonctionnel',
status: 'Problems',
},
];
const renderItem = ({item, index}) => {
return (
<View>
<View style={{flexDirection: 'row'}}>
<CheckBoxCustom />
<Text style={{marginLeft: 10}}>{item.name} </Text>
</View>
</View>
);
};
const separator = () => {
return (
<View
style={{
height: 1,
backgroundColor: '#f1f1f1',
marginBottom: 12,
marginTop: 12,
}}
/>
);
};
const FirstRoute = () => (
<FlatList
style={{marginTop: 20}}
data={data}
keyExtractor={(e, i) => i.toString()}
renderItem={renderItem}
ItemSeparatorComponent={separator}
/>
);
const SecondRoute = () => (
<View style={[styles.scene, {backgroundColor: 'white'}]} />
);
const initialLayout = {width: Dimensions.get('window').width};
const renderScene = SceneMap({
first: FirstRoute,
second: SecondRoute,
});
const ReportScreen = ({navigation}) => {
const nav = useNavigation();
const layout = useWindowDimensions();
const [index, setIndex] = useState(0);
const [routes] = useState([
{key: 'first', title: 'Problemes'},
{key: 'second', title: 'Besoins complémentaitaires'},
]);
const goToScreen = () => {
navigation.navigate('GetCheckBoxData', {title: 'Hii all'});
};
const [checked, setChecked] = useState({});
const checkToggle = id => {
setChecked(checked => ({
...checked,
[id]: !checked[id],
}));
};
return (
<SafeAreaView style={styles.safearea}>
<Header title="Report" />
<ScrollView showsVerticalScrollIndicator={false} bounces={false}>
<View style={{flexDirection: 'row', marginTop: 20}}>
<View style={{flex: 1, height: 1, backgroundColor: '#ccc'}} />
</View>
<View style={styles.cardView}>
<View style={styles.subView}>
<Image
style={styles.image}
source={require('../Assets/UIPracticeImage/H1.jpg')}
/>
<View style={styles.internalSubView}>
<View style={styles.nameView}>
<Text style={styles.nameText}>Pine Hill Green Caban</Text>
</View>
<View style={styles.dateView}>
<Text style={styles.dateText}>May 22-27</Text>
</View>
</View>
</View>
</View>
<View style={{flexDirection: 'row'}}>
<View style={{flex: 1, height: 1, backgroundColor: '#ccc'}} />
</View>
<View
style={{
// backgroundColor: 'lime',
flex: 1,
height: 385,
width: '100%',
}}>
<TabView
navigationState={{index, routes}}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={initialLayout}
style={styles.container}
renderTabBar={props => (
<TabBar
tabStyle={{alignItems: 'flex-start', width: 'auto'}}
{...props}
renderLabel={({route, color}) => (
<Text style={{color: 'black'}}>{route.title}</Text>
)}
style={{backgroundColor: 'white'}}
/>
)}
/>
</View>
<Button title="Click me" onPress={goToScreen} />
</ScrollView>
</SafeAreaView>
);
};
export default ReportScreen;
const styles = StyleSheet.create({
safearea: {
marginHorizontal: 20,
},
cardView: {
borderRadius: 10,
marginVertical: 10,
paddingVertical: 8,
},
subView: {
flexDirection: 'row',
},
image: {
height: 80,
width: 110,
borderRadius: 10,
},
internalSubView: {
justifyContent: 'space-between',
flex: 1,
},
nameView: {
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
marginLeft: 10,
},
nameText: {
fontWeight: 'bold',
width: '45%',
fontSize: 15,
},
dateView: {
flexDirection: 'row',
alignItems: 'center',
marginLeft: 10,
justifyContent: 'space-between',
},
dateText: {
width: 80,
},
listTab: {
flexDirection: 'row',
marginBottom: 20,
marginTop: 20,
},
btnTab: {
borderWidth: 3,
borderColor: 'white',
flexDirection: 'row',
marginRight: 10,
},
btnTabActive: {
borderWidth: 3,
borderBottomColor: '#fdd83d',
borderColor: 'white',
},
scheduleButton: {
backgroundColor: '#fdd83d',
alignItems: 'center',
paddingVertical: 15,
borderRadius: 10,
marginTop: 15,
},
container: {
marginTop: 20,
},
scene: {
flex: 1,
},
});
[![UI image][1]][1]
[1]: https://i.stack.imgur.com/AuLT8.png
You may want to lift the checkbox state to the parent component, i.e. make the checkboxes controlled, and collect the checked checkbox values. For this I'm assuming your data items have an id property, but any unique item property will suffice.
Example:
export function CheckBoxCustom({ checked, onPress }) {
return (
<SafeAreaView>
<TouchableOpacity
style={{
backgroundColor: "white",
width: 20,
height: 20,
borderWidth: 2,
borderColor: "#ddd",
}}
onPress={onPress}
>
{checked ?? <IconAntDesign name="check" size={15} color={"black"} />}
</TouchableOpacity>
</SafeAreaView>
);
}
...
const [checked, setChecked] = useState({});
const checkToggle = id => {
setChecked(checked => ({
...checked,
[id]: !checked[id],
}));
};
const renderItem = ({ item, index }) => {
return (
<View>
<View style={{ flexDirection: "row" }}>
<CheckBoxCustom
checked={checked[item.id]}
onPress={() => checkToggle(item.id)}
/>
<Text style={{ marginLeft: 10 }}>{item.name}</Text>
</View>
</View>
);
};
<FlatList
data={dataList}
keyExtractor={(e, i) => i.toString()}
renderItem={renderItem}
ItemSeparatorComponent={separator}
/>;
If your data hasn't any good GUID candidates then I suggest augmenting your data to include good GUIDs.
To pass the checked/selected items filter the dataList array.
Example:
const selected = dataList.filter(
item => checked[item.id]
);
// pass selected in navigation action

add current time with text input

enter image description here Iam new with react native,so maybe my question seems silly to all excepts.I want to add current time in text input.(i designd todo app,that show the todo list,now i want to show time in todo list,for eg i enter todo(complete frontend)and add,that contain complete and delete button,now i want to add time in that(task adding time).my code are following below,
import React from 'react';
import {
StyleSheet,
SafeAreaView,
View,
TextInput,
Text,
FlatList,
TouchableOpacity,
Alert,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AsyncStorage from '#react-native-async-storage/async-storage';
const COLORS = {primary: '#1f145c', white: '#fff'};
const App = () => {
const \[todos, setTodos\] = React.useState(\[\]);
const \[textInput, setTextInput\] = React.useState('');
React.useEffect(() => {
getTodosFromUserDevice();
}, \[\]);
React.useEffect(() => {
saveTodoToUserDevice(todos);
}, \[todos\]);
const addTodo = () => {
if (textInput == '') {
Alert.alert('Error', 'Please input todo');
} else {
const newTodo = {
id: Math.random(),
task: textInput,
completed: false,
};
setTodos(\[...todos, newTodo\]);
setTextInput('');
}
};
const saveTodoToUserDevice = async todos => {
try {
const stringifyTodos = JSON.stringify(todos);
await AsyncStorage.setItem('todos', stringifyTodos);
} catch (error) {
console.log(error);
}
};
const getTodosFromUserDevice = async () => {
try {
const todos = await AsyncStorage.getItem('todos');
if (todos != null) {
setTodos(JSON.parse(todos));
}
} catch (error) {
console.log(error);
}
};
const markTodoComplete = todoId => {
const newTodosItem = todos.map(item => {
if (item.id == todoId) {
return {...item, completed: true};
}
return item;
});
setTodos(newTodosItem);
};
const deleteTodo = todoId => {
const newTodosItem = todos.filter(item => item.id != todoId);
setTodos(newTodosItem);
};
const clearAllTodos = () => {
Alert.alert('Confirm', 'Clear todos?', \[
{
text: 'Yes',
onPress: () => setTodos(\[\]),
},
{
text: 'No',
},
\]);
};
const ListItem = ({todo}) => {
return (
<View style={styles.listItem}>
<View style={{flex: 1}}>
<Text
style={{
fontWeight: 'bold',
fontSize: 20,
color: COLORS.primary,
textDecorationLine: todo?.completed ? 'line-through' : 'none',
}}>
{todo?.task}
</Text>
</View>
{!todo?.completed && (
<TouchableOpacity onPress={() => markTodoComplete(todo.id)}>
<View style={\[styles.actionIcon, {backgroundColor: 'green'}\]}>
<Icon name="done" size={20} color="white" />
</View>
</TouchableOpacity>
)}
<TouchableOpacity onPress={() => deleteTodo(todo.id)}>
<View style={styles.actionIcon}>
<Icon name="delete" size={20} color="white" />
</View>
</TouchableOpacity>
</View>
);
};
return (
<SafeAreaView
style={{
flex: 1,
backgroundColor: 'white',
}}>
<View style={styles.header}>
<Text
style={{
fontWeight: 'bold',
fontSize: 20,
color: COLORS.primary,
}}>
TODO APP
</Text>
<Icon name="delete" size={25} color="red" onPress={clearAllTodos} />
</View>
<FlatList
showsVerticalScrollIndicator={false}
contentContainerStyle={{padding: 20, paddingBottom: 100}}
data={todos}
renderItem={({item}) => <ListItem todo={item} />}
/>
<View style={styles.footer}>
<View style={styles.inputContainer}>
<TextInput
value={textInput}
placeholder="Add Todo"
onChangeText={text => setTextInput(text)}
/>
</View>
<TouchableOpacity onPress={addTodo}>
<View style={styles.iconContainer}>
<Icon name="add" color="white" size={30} />
</View>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
footer: {
position: 'absolute',
bottom: 0,
width: '100%',
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 20,
backgroundColor: COLORS.white,
},
inputContainer: {
height: 50,
paddingHorizontal: 20,
elevation: 40,
backgroundColor: COLORS.white,
flex: 1,
marginVertical: 20,
marginRight: 20,
borderRadius: 30,
},
iconContainer: {
height: 50,
width: 50,
backgroundColor: COLORS.primary,
elevation: 40,
borderRadius: 25,
justifyContent: 'center',
alignItems: 'center',
},
listItem: {
padding: 20,
backgroundColor: COLORS.white,
flexDirection: 'row',
elevation: 12,
borderRadius: 7,
marginVertical: 10,
},
actionIcon: {
height: 25,
width: 25,
backgroundColor: COLORS.white,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red',
marginLeft: 5,
borderRadius: 3,
},
header: {
padding: 20,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
});
export default App;][1]
i got the answer ,answer is following below,
import React from 'react';
import {
StyleSheet,
SafeAreaView,
View,
TextInput,
Text,
FlatList,
TouchableOpacity,
Alert,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AsyncStorage from '#react-native-async-storage/async-storage';
const COLORS = {primary: '#1f145c', white: '#fff'};
const App = () => {
const [todos, setTodos] = React.useState([]);
const [textInput, setTextInput] = React.useState('');
React.useEffect(() => {
getTodosFromUserDevice();
}, []);
React.useEffect(() => {
saveTodoToUserDevice(todos);
}, [todos]);
const addTodo = () => {
if (textInput == '') {
Alert.alert('Error', 'Please input todo');
} else {
const newTodo = {
id: Math.random(),
task: textInput,
completed: false,
time: getCurrentTime()
};
setTodos([...todos, newTodo]);
setTextInput('');
}
};
const saveTodoToUserDevice = async todos => {
try {
const stringifyTodos = JSON.stringify(todos);
await AsyncStorage.setItem('todos', stringifyTodos);
} catch (error) {
console.log(error);
}
};
const getTodosFromUserDevice = async () => {
try {
const todos = await AsyncStorage.getItem('todos');
if (todos != null) {
setTodos(JSON.parse(todos));
}
} catch (error) {
console.log(error);
}
};
***const getCurrentTime = () => {
let today = new Date();
let date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
let dateTime = date + '/' + time;
return dateTime;
}***
const markTodoComplete = todoId => {
const newTodosItem = todos.map(item => {
if (item.id == todoId) {
return {...item, completed: true};
}
return item;
});
setTodos(newTodosItem);
};
const deleteTodo = todoId => {
const newTodosItem = todos.filter(item => item.id != todoId);
setTodos(newTodosItem);
};
const clearAllTodos = () => {
Alert.alert('Confirm', 'Clear todos?', [
{
text: 'Yes',
onPress: () => setTodos([]),
},
{
text: 'No',
},
]);
};
const comdel = () => {
Alert.alert('select status', 'Complete or Delete', [
{
text: 'Delete',
onPress: () => setTodos([]),
},
{
text: 'Complete',
onPress: () => {markTodoComplete(todo.id)}
},
]);
};
const ListItem = ({todo}) => {
return (
<View style={styles.listItem}>
<View style={{flex: 1}}>
<Text
style={{
fontWeight: 'bold',
fontSize: 20,
color: COLORS.primary,
textDecorationLine: todo?.completed ? 'line-through' : 'none',
}}>
{todo?.task}
</Text>
</View>
{/* {!todo?.completed && (
<TouchableOpacity onPress={() => markTodoComplete(todo.id)}>
<View style={[styles.actionIcon, {backgroundColor: 'green'}]}>
<Icon name="done" size={20} color="white" />
</View>
</TouchableOpacity>
)} */}
{/* <TouchableOpacity onPress={() => deleteTodo(todo.id)}>
<View style={styles.actionIcon}>
<Icon name="delete" size={20} color="white" />
</View>
</TouchableOpacity> */}
<View>
<Text>
{todo?.time}
</Text>
</View>
<Icon name="menu" size={40} color="#a9a9a9" onPress={comdel} />
</View>
);
};
return (
<SafeAreaView
style={{
flex: 1,
backgroundColor: 'white',
}}>
<View style={styles.header}>
<Text
style={{
fontWeight: 'bold',
fontSize: 20,
color: COLORS.primary,
}}>
TODO APP
</Text>
<Icon name="delete" size={25} color="red" onPress={comdel} />
</View>
<FlatList
showsVerticalScrollIndicator={false}
contentContainerStyle={{padding: 20, paddingBottom: 100}}
data={todos}
renderItem={({item}) => <ListItem todo={item} />}
/>
<View style={styles.footer}>
<View style={styles.inputContainer}>
<TextInput
value={textInput}
placeholder="Add Todo"
onChangeText={text => setTextInput(text)}
/>
</View>
<TouchableOpacity onPress={addTodo}>
<View style={styles.iconContainer}>
<Icon name="add" color="white" size={30} />
</View>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
footer: {
position: 'absolute',
bottom: 0,
width: '100%',
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 20,
backgroundColor: COLORS.white,
},
inputContainer: {
height: 50,
paddingHorizontal: 20,
elevation: 40,
backgroundColor: COLORS.white,
flex: 1,
marginVertical: 20,
marginRight: 20,
borderRadius: 30,
},
iconContainer: {
height: 50,
width: 50,
backgroundColor: COLORS.primary,
elevation: 40,
borderRadius: 25,
justifyContent: 'center',
alignItems: 'center',
},
listItem: {
padding: 40,
backgroundColor: "#d3d3d3",
flexDirection: 'column',
elevation: 12,
borderRadius: 7,
marginVertical: 10,
},
actionIcon: {
height: 25,
width: 25,
backgroundColor: COLORS.white,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red',
marginLeft: 5,
borderRadius: 3,
},
header: {
padding: 20,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
});
export default App;

Updates State when SectionList has finished rendering

I have a sectionlist with an ActivityIndicator at the footer. The ActivityIndicator doesn't go away even after the list has rendered every item. The data is local data.
I do know that I have to use React Hook, so I created _handleLoadMore() to update the state, but I don't know how to detect once the list has come to the end.
This is my code
import React, {useState, useEffect} from 'react';
import {
View,
Text,
StyleSheet,
SectionList,
ActivityIndicator,
} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
export default function TransactionHistoryList({data}: {data: any}) {
const [loadMore, setLoadMore] = useState('true')
const _handleLoadMore = () => {
//what to put here
}
const extractKey = ({
id,
}: {
id: any;
name: any;
accountNumber: any;
type: any;
amount: any;
}) => id;
const renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '94%',
backgroundColor: '#000',
alignSelf: 'center',
}}
/>
);
};
const footerComponent = () => {
if (!_handleLoadMore) return null;
return (
<View
style={{
position: 'relative',
paddingVertical: 20,
borderTopWidth: 1,
marginTop: 10,
marginBottom: 10,
}}>
<ActivityIndicator
animating
size="small"
color="#CED0CE"
hidesWhenStopped={true}
/>
</View>
);
};
return (
<SafeAreaView>
<View style={styles.container}>
<Text style={styles.transactionhistory}>Transaction History</Text>
<SectionList
contentContainerStyle={{paddingBottom: 500}}
maxToRenderPerBatch={7}
onEndReachedThreshold={2}
updateCellsBatchingPeriod={4000}
ItemSeparatorComponent={renderSeparator}
sections={data}
renderSectionHeader={({section}) => {
return <Text style={styles.date}>{section.title}</Text>;
}}
renderItem={({item}) => {
return (
<View style={styles.item}>
<Text>
<View>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.accountNumber}>
{item.accountNumber}
</Text>
</View>
</Text>
<View style={styles.amountContainer}>
<Text
style={[
item.type == 'in' ? styles.moneyIn : styles.moneyOut,
]}>
{item.amount}
</Text>
</View>
</View>
);
}}
ListFooterComponent= {footerComponent}
keyExtractor={extractKey}
/>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
marginLeft: 20,
marginRight: 20,
marginTop: 120,
flex: -200,
//paddingBottom: 10
},
transactionhistory: {
fontWeight: 'bold',
fontSize: 18,
paddingBottom: 10,
paddingLeft: 25,
},
item: {
flexDirection: 'row',
justifyContent: 'space-between',
marginRight: 20,
marginLeft: 25,
paddingBottom: 10,
paddingTop: 10,
},
date: {
padding: 10,
marginBottom: 15,
backgroundColor: '#e0e0e0',
fontFamily: 'OpenSans-Bold',
fontSize: 15,
paddingLeft: 25,
},
name: {
fontSize: 14,
fontFamily: 'OpenSans-SemiBold',
},
accountNumber: {
fontSize: 12,
fontFamily: 'OpenSans-Regular',
},
amountContainer: {
paddingTop: 8,
},
moneyIn: {
color: '#689f38',
letterSpacing: 0.8,
fontSize: 16,
fontFamily: 'OpenSans-SemiBold',
},
moneyOut: {
color: '#b71c1c',
letterSpacing: 0.8,
fontSize: 16,
fontFamily: 'OpenSans-SemiBold',
},
loading: {
color: '#CED0CE',
},
});
section-list support on-scroll event and you can can hide/show activity-indicator feature quite smoothly with on scroll
Example:
const isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
const paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom;
};
<SectionList
contentContainerStyle={{paddingBottom: 500}}
maxToRenderPerBatch={7}
onEndReachedThreshold={2}
onScroll={({nativeEvent}) => {
if (isCloseToBottom(nativeEvent)) {
if(!this.state.fetching_status){
//what you want to do when the screen reached end of screen
//console.log or something usefull
}
}
}}
.../>
I think it is possible to use onEndReached prop of SectionList in your case https://reactnative.dev/docs/sectionlist#onendreached
That is the correct place to write your logic to load next "page" of your items

How to set the height of the image as the flex height

In my react-native application, I want to set the height of an image as the flex height. How can I do that? At present, Im using the height as the device-heigth / 3. But when it comes to the smaller screens, it makes issues. How can I achieve this as the height of the image as the flex height? My code works properly in 5 inch devices, but when it comes to 4, the image makes a mess.
render() {
return (
<View style={styles.container}>
<View style={styles.postCommentWrapper}>
<ScrollView
ref={view => {
this.scrollView = view;
}}
>
<Animated.View>
<PostProfileBar
profile={this.state.post.author}
timeAgo={this.state.post.timeAgo}
/>
<ClickableImage
source={{ uri: this.state.post.postImage }}
height={height * (3 / 10)}
width={width}
onPress={() => alert("Image Clicked")}
/>
</Animated.View>
<CommentFlatList
data={this.state.data}
refreshing={this.state.refreshing}
/>
</ScrollView>
</View>
<View
style={[
styles.commentInputWrapper,
{ flex: this.state.commentBoxStyles.flex }
]}
>
<InputWithClickableIcon
iconName="upload"
placeholder="Type Comment"
isFocused={true}
fontSize={this.state.comment.value.length > 0 ? 16 : 20}
value={this.state.comment.value}
multiline={true}
maxLength={500}
height={this.state.commentBoxStyles.height}
borderRadius={this.state.commentBoxStyles.borderRadius}
onChangeText={value => this.onChangeComment(value)}
onPress={() => this.uploadComment()}
invalidInput={styles.invalidInput}
valid={this.state.comment.valid}
touched={this.state.comment.touched}
disabled={!this.state.comment.valid}
/>
</View>
</View>
);
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerTitle: "Comment",
headerTitleStyle: {
paddingLeft: "20%",
paddingRight: "20%"
},
headerStyle: {
paddingRight: 10,
paddingLeft: 10
},
headerLeft: (
<Icon
name={"close"}
size={30}
onChangeText={this.onChangeText}
onPress={() => {
navigation.goBack();
}}
/>
)
};
};
}
const styles = StyleSheet.create({
container: {
borderWidth: 3,
borderColor: "yellow",
flex: 1
},
postCommentWrapper: {
borderWidth: 2,
borderColor: "blue",
flex: 16,
marginTop: 10
},
// commentListWrapper: {
// borderWidth: 2,
// borderColor: "green",
// flex: 8,
// marginTop: 10
// },
commentInputWrapper: {
flex: 2,
borderWidth: 2,
borderColor: "purple",
justifyContent: "flex-end",
marginTop: 5
}
});
ClickableImage Component
import React from "react";
import { TouchableOpacity, Image, StyleSheet } from "react-native";
const clickableImage = props => (
<TouchableOpacity onPress={props.onPress}>
<Image
{...props}
style={[
styles.image,
props.style,
{ height: props.height },
{ width: props.width }
]}
/>
</TouchableOpacity>
);
const styles = StyleSheet.create({
image: {
marginTop: 10,
flexDirection: "row",
alignItems: "center"
}
});
export default clickableImage;
Since you've already passed the style props to the ClickableImage, therefore you can do
<ClickableImage
source={{ uri: this.state.post.postImage }}
style={{flex: 1}}
onPress={() => alert("Image Clicked")}
/>
You also need to pass the styles to TouchableOpacity for the flex inside the container to work
<TouchableOpacity style={props.style} onPress={props.onPress}> //... Pass the relevant styles here

Not able to refer to drawer layout in react native

I have my Js file like this.
"use strict"
var React = require('react-native')
var {
AppRegistry,
Component,
StyleSheet,
Text,
View,
TouchableNativeFeedback,
Image,
DrawerLayoutAndroid,
Navigator,
ListView,
ToolbarAndroid
} = React;
var ToolbarAndroid = require('ToolbarAndroid');
var Drawer = require('react-native-drawer');
import Screen2 from './Screen2';
import Screen3 from './Screen3';
class Screen1 extends Component {
openDrawer(){
this.refs['DRAWER'].openDrawer()
}
_handlePress(screen_name,loggedIn) {
this.refs.DRAWER.closeDrawer(),
this.refs.navigator.push(
{id: screen_name,
})
}
renderScene(route, navigator) {
switch(route.id){
case 'Screen1': return (
DrawerLayoutAndroid
drawerWidth={300}
ref={'DRAWER'}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => navigationView}>
<View style={styles.container}>
<ToolbarAndroid
navIcon={require('image!ic_menu_white')}
titleColor="white"
style={styles.toolbar}
onIconClicked={() => this.openDrawer()}
onActionSelected={this.onActionSelected} />
</View>
<ListView contentContainerStyle={styles.list}
dataSource={this.state.dataSource}
renderRow={this.renderItem.bind(this)}
/>
</DrawerLayoutAndroid>
);
case 'Screen2': return (<Screen2 navigator={navigator} />)
case 'Screen3': return (<Screen3 navigator={navigator} />)
}
}
render(){
navigationView = (
<View style={styles.header}>
<View style={styles.HeadingContainer}>
<TouchableNativeFeedback>
<View style={styles.HeadingItem}>
<Text style={styles.menuText}>
Welcome!
</Text>
<Text style={styles.menuText}>
Guest
</Text>
</View>
</TouchableNativeFeedback>
</View>
<View style={{flex: 4, backgroundColor: 'white'}}>
<TouchableNativeFeedback onPress={this._handlePress.bind(this,'Screen1')}>
<View style={styles.menuContainer}>
<Text style={styles.menu}>Albums</Text>
<Image
source={require('image!ic_menu_arrow')}
style={{flex : 1,width: 10, height: 10, margin: 20}} />
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback onPress={this._handlePress.bind(this,'Screen2')}>
<View style={styles.menuContainer}>
<Text style={styles.menu}>Member Validation</Text>
<Image
source={require('image!ic_menu_arrow')}
style={{flex : 1,width: 10, height: 10, margin: 20}} />
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback onPress={this._handlePress.bind(this,'Screen3')}>
<View style={styles.menuContainer}>
<Text style={styles.menu}>Settings</Text>
<Image
source={require('image!ic_menu_arrow')}
style={{flex : 1,width: 10, height: 10, margin: 20}} />
</View>
</TouchableNativeFeedback>
</View>
</View>
);
return(
<
<Navigator
initialRoute={{id: 'Screen1'}}
renderScene={this.renderScene.bind(this)}
ref='navigator'
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.FloatFromRight;
}} />
);
}
}
var styles = StyleSheet.create({
list: {
justifyContent: 'center',
flexDirection: 'row',
flexWrap: 'wrap'
},
renderLoading: {
padding: 30,
marginTop: 65,
alignItems: 'center'
},
container: {
flexDirection: 'column',
backgroundColor: '#FAFAFA',
},
backgroundImage: {
flex: 1,
resizeMode: 'cover', // or 'stretch'
},
rightContainer: {
flex: 1,
},
year: {
textAlign: 'center',
},
thumbnail: {
width: 53,
height: 81,
},
listView: {
paddingTop: 20,
backgroundColor: '#F5FCFF',
margin:20
},
movie: {
height: 150,
flex: 1,
alignItems: 'center',
flexDirection: 'column',
},
titles: {
fontSize: 10,
marginBottom: 8,
width: 90,
textAlign: 'center',
},
header: {
flex: 1,
flexDirection: 'column',
},
menuContainer: {
flexDirection: 'row',
},
HeadingItem: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: 10,
},
HeadingContainer: {
flex: 1,
backgroundColor: '#00a2ed',
},
menuText: {
fontSize: 14,
color: 'black',
},
menu: {
flex: 4,
fontSize: 12,
color: 'black',
margin: 20,
},
toolbar: {
backgroundColor: '#00a2ed',
height: 56,
},
});
export default Screen1;
Now I am not able to refer to Drawer reference variable 'DRAWER'.It gives me error undefined is not an object.Not able to open or close drawer.
I want DrawerLayout for Screen1 only so I am rendering it in RenderScene method.
If i implement DrawerLayout in render method,then I am able to refer to reference Drawer.
Can we create reference in render method only.IF yes how to solve this problem.
Accessing drawer object using state object of component.
"use strict"
var React = require('react-native')
var {
AppRegistry,
Component,
StyleSheet,
Text,
View,
TouchableNativeFeedback,
Image,
DrawerLayoutAndroid,
Navigator,
ListView,
ToolbarAndroid
} = React;
var ToolbarAndroid = require('ToolbarAndroid');
var Drawer = require('react-native-drawer');
import Screen2 from './Screen2';
import Screen3 from './Screen3';
class Screen1 extends Component {
constructor(props) {
super(props);
this.state = {
drawer: null,
};
}
setDrawer = (drawer) => {
this.setState({
drawer
});
};
openDrawer(){
this.state.drawer.openDrawer()
}
_handlePress(screen_name,loggedIn) {
this.state.drawer.closeDrawer(),
this.refs.navigator.push(
{id: screen_name,
})
}
renderScene(route, navigator) {
switch(route.id){
case 'Screen1':
const { drawer } = this.state;
return (
<DrawerLayoutAndroid
drawerWidth={300}
ref={(drawer) => { !this.state.drawer ? this.setDrawer(drawer) : null }}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => navigationView}>
<View style={styles.container}>
<ToolbarAndroid
navIcon={require('image!ic_menu_white')}
titleColor="white"
style={styles.toolbar}
onIconClicked={() => this.openDrawer()}
onActionSelected={this.onActionSelected} />
</View>
<ListView contentContainerStyle={styles.list}
dataSource={this.state.dataSource}
renderRow={this.renderItem.bind(this)}
/>
</DrawerLayoutAndroid>
);
case 'Screen2': return (<Screen2 navigator={navigator} />)
case 'Screen3': return (<Screen3 navigator={navigator} />)
}
}
render(){
navigationView = (
<View style={styles.header}>
<View style={styles.HeadingContainer}>
<TouchableNativeFeedback>
<View style={styles.HeadingItem}>
<Text style={styles.menuText}>
Welcome!
</Text>
<Text style={styles.menuText}>
Guest
</Text>
</View>
</TouchableNativeFeedback>
</View>
<View style={{flex: 4, backgroundColor: 'white'}}>
<TouchableNativeFeedback onPress={this._handlePress.bind(this,'Screen1')}>
<View style={styles.menuContainer}>
<Text style={styles.menu}>Albums</Text>
<Image
source={require('image!ic_menu_arrow')}
style={{flex : 1,width: 10, height: 10, margin: 20}} />
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback onPress={this._handlePress.bind(this,'Screen2')}>
<View style={styles.menuContainer}>
<Text style={styles.menu}>Member Validation</Text>
<Image
source={require('image!ic_menu_arrow')}
style={{flex : 1,width: 10, height: 10, margin: 20}} />
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback onPress={this._handlePress.bind(this,'Screen3')}>
<View style={styles.menuContainer}>
<Text style={styles.menu}>Settings</Text>
<Image
source={require('image!ic_menu_arrow')}
style={{flex : 1,width: 10, height: 10, margin: 20}} />
</View>
</TouchableNativeFeedback>
</View>
</View>
);
return(
<
<Navigator
initialRoute={{id: 'Screen1'}}
renderScene={this.renderScene.bind(this)}
ref='navigator'
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.FloatFromRight;
}} />
);
}
}
var styles = StyleSheet.create({
list: {
justifyContent: 'center',
flexDirection: 'row',
flexWrap: 'wrap'
},
renderLoading: {
padding: 30,
marginTop: 65,
alignItems: 'center'
},
container: {
flexDirection: 'column',
backgroundColor: '#FAFAFA',
},
backgroundImage: {
flex: 1,
resizeMode: 'cover', // or 'stretch'
},
rightContainer: {
flex: 1,
},
year: {
textAlign: 'center',
},
thumbnail: {
width: 53,
height: 81,
},
listView: {
paddingTop: 20,
backgroundColor: '#F5FCFF',
margin:20
},
movie: {
height: 150,
flex: 1,
alignItems: 'center',
flexDirection: 'column',
},
titles: {
fontSize: 10,
marginBottom: 8,
width: 90,
textAlign: 'center',
},
header: {
flex: 1,
flexDirection: 'column',
},
menuContainer: {
flexDirection: 'row',
},
HeadingItem: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: 10,
},
HeadingContainer: {
flex: 1,
backgroundColor: '#00a2ed',
},
menuText: {
fontSize: 14,
color: 'black',
},
menu: {
flex: 4,
fontSize: 12,
color: 'black',
margin: 20,
},
toolbar: {
backgroundColor: '#00a2ed',
height: 56,
},
});
export default Screen1;
The best and easy solution of your problem is make separate file for Navigating different scenes which contains only Navigator component, there you can navigate different scenes with suitable condition.
Make different files as:
1. navigator.js
2. screen1.js
3. screen2.js
in navigator.js keep the code as
<Navigator
initialRoute={{id: 'Screen1'}}
renderScene={this.renderScene.bind(this)}
ref='navigator'
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.FloatFromRight;
}} />
also do switch case statement here:
renderScene(route, navigator) {
switch(route.id){
case 'Screen1': return (<Screen1 navigator={navigator}>
);
case 'Screen2': return (<Screen2 navigator={navigator} />)
case 'Screen3': return (<Screen3 navigator={navigator} />)
}
Then make individual component of screen1, screen2, screen3 and place all components like
<DrawerLayout><Toolbar/><ListView/></DrawerLayout>
in which screen you want in their respective render() function, also you can call openDrawer() like function in your specific screen.
This way you can reduced your messy code organization and complete your code.
Hope this will help your problem.