react-native (js) : generalise a function - javascript

I have two functions which I would like to condense into one (with another argument). They are called like so:
<ListView
automaticallyAdjustContentInsets={false}
dataSource={this.state.dataSource_proj}
renderRow={this.renderProjRow.bind(this)}/>
<ListView
automaticallyAdjustContentInsets={false}
dataSource={this.state.dataSource_map}
renderRow={this.renderMapRow.bind(this)}/>
And the functions are:
renderProjRow(rowData, sectionID, rowID) {
return (
<TouchableHighlight onPress={() => this.rowProjPressed(rowData.project_name)}
underlayColor='#dddddd'>
<View>
<View style={styles.rowContainer}>
<Image source={{uri: 'Letter-' + rowData.project_name.substr(0,1).toUpperCase()}}
style={styles.thumb}/>
<View style={styles.textContainer}>
<Text style={styles.title}
numberOfLines={1}>{rowData.project_name}</Text>
</View>
</View>
<View Style={styles.separator}/>
</View>
</TouchableHighlight>
);
}
renderMapRow(rowData, sectionID, rowID) {
return (
<TouchableHighlight onPress={() => this.rowMapPressed(rowData)}
underlayColor='#dddddd'>
<View>
<View style={styles.rowContainer}>
<Image source={{uri: 'Letter-' + rowData.map_name.substr(0,1).toUpperCase()}}
style={styles.thumb}/>
<View style={styles.textContainer}>
<Text style={styles.title}
numberOfLines={1}>{rowData.map_name}</Text>
</View>
</View>
<View Style={styles.separator}/>
</View>
</TouchableHighlight>
);
}
I would like to just have one function: renderRow, which takes rowData.project_name if the data-source is dataSource_proj and rowData.map_name if the data-source is dataSource_map.
However, aside from using eval ... I'm not sure how to implement this in a proper way.

Related

React native : Flatlist inside scrollview

My goal is for this entire block to be scrollable.
I tried all kinds of ways to achieve the goal but without success.
I tried with ListHeaderComponent and moved the entire top view to it and it didn't work.
And I also tried <FlatList nestedScrollEnabled />
And it didn't work either.
What is the correct way to reach the scroll?
I come from here :
const renderAccordians = () => {
const items: JSX.Element[] = [];
areaData.forEach(item => {
items.push(<Accordian item={item} key={item.title} />);
});
return items;
};
To here :
return (
<View>
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons size={24} name={data.checked ? 'check-box' : 'check-box-outline-blank'} color={'black'} />
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'} size={30} color={'black'} />
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={false}
renderItem={({ item, index }) => (
<View>
<TouchableOpacity style={[styles.childRow, styles.button]} onPress={() => onClick(index)}>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);
Since your FlatList will be part of an Accordion component, you "can't" embed the ExpandButton inside the Flatlist > ListHeaderComponent ... cause It'll simply hide the whole FlatList along with it's Header when you collapse your accorddion...
keyExtractor is also missing in your FlatList .. I added index as a key here which is not recommended BTW, you better use a unique field in your listItem like id...
return (
<View style={{ flex: 1}}> // <<--- Look here
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons
size={24}
name={data.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons
name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'}
size={30}
color={'black'}
/>
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={true} // <<--- Look here
keyExtractor={(_, index) => index.toString()} // <<=== Look here
contentContainerStyle={{flexGrow: 1}} // <<--- Look here
renderItem={({ item, index }) => (
<View>
<TouchableOpacity
style={[styles.childRow, styles.button]}
onPress={() => onClick(index)}
>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);
If it does not work, I think you should create a component and use map datalist to render all the items and putting them into the ScrollView tag.
<ScrollView
style={styles.messageContain}
ref={ref => {
this.scrollView = ref;
}}
{data.data.map((item, index) => {
return <YourComponent key={index} data={item} />;
})}
</ScrollView>

How can conditional rendering for array map

I have condition for profile page
I want to show user profile data
name . age etc..So I map array to get each user data
but problem is when there is no data in firestore , this profile page is empty
this is really disappointed
I want to conditional rendering the following rendering
But error is
jsx expression must have one parent element
so how can render this correctly
return (
<SafeAreaView style={styles.container}>
{values.map((value)=>(
<React.Fragment key={value.id}>
<View style={styles.header}></View>
<Image style={styles.avatar} source={{uri : value.photo}}/>
<View style={styles.body}>
<View style={styles.bodyContent}>
<Text style={styles.name}>{value.displayName}</Text>
<View style={styles.label}>
<Text >My Job is - </Text>
<Text>{value.job}</Text>
</View>
<View style={styles.label}>
<Text>My Age is - </Text>
<Text >{value.age}</Text>
</View>
<View style={styles.label}>
<Text>My Gender is - </Text>
<Text >{value.gender}</Text>
</View>
<View style={styles.label}>
<Text>I want to meet - </Text>
<Text >{value.interestIn}</Text>
</View>
</View>
</View>
</React.Fragment>
))}
<View style={tw("p-10 flex-row items-center justify-between px-5")}>
<Pressable
style={
tw('p-3 rounded-xl bg-red-400')} onPress={goedit}>
<Text style={styles.text}>Edit Profile</Text>
</Pressable>
<Pressable
style={
tw('p-3 rounded bg-red-400')} onPress={logout}>
<Text style={styles.text}>LOGOUT</Text>
</Pressable>
</View>
</SafeAreaView>
)
I want to show user profile page as template even no data in firestore
can someone help me
Just add a <> ontop of the map and then </> on the bottom to close it. If you need flex then you can switch out the <></> for
You could try something like this, but paste your logic inside if statement:
const renderValues = () => {
values.map((value) => {
if (value) {
return (
<View>
<Text>data</Text>
</View>
);
} else {
return <View>no data</View>;
}
});
};
return <>{renderValues()}</>;
const renderValues = () => {
values.map((value) => {
if (value) {
return (
<React.Fragment key={value.id}>
<View style={styles.header} />
<Image style={styles.avatar} source={{ uri: value.photo }} />
<View style={styles.body}>
<View style={styles.bodyContent}>
<Text style={styles.name}>{value.displayName}</Text>
<View style={styles.label}>
<Text>My Job is - </Text>
<Text>{value.job}</Text>
</View>
<View style={styles.label}>
<Text>My Age is - </Text>
<Text>{value.age}</Text>
</View>
<View style={styles.label}>
<Text>My Gender is - </Text>
<Text>{value.gender}</Text>
</View>
<View style={styles.label}>
<Text>I want to meet - </Text>
<Text>{value.interestIn}</Text>
</View>
</View>
</View>
</React.Fragment>
);
} else {
return <View>no data</View>;
}
});
};
return (
<SafeAreaView style={styles.container}>
<>
{renderValues()}
<View style={tw('p-10 flex-row items-center justify-between px-5')}>
<Pressable style={tw('p-3 rounded-xl bg-red-400')} onPress={goedit}>
<Text style={styles.text}>Edit Profile</Text>
</Pressable>
<Pressable style={tw('p-3 rounded bg-red-400')} onPress={logout}>
<Text style={styles.text}>LOGOUT</Text>
</Pressable>
</View>
</>
</SafeAreaView>
);

localStorage doesn't work in TouchableOpacity tag

I want to use localStorage and move to another page at the same time, but only moving work, I can't get the value
const pressHandlerMapTest = () => {
navigation.navigate("TestMapScreen");
};
return (
<ImageBackground style={styles.background}>
<View style={styles.tourWindow}>
<TouchableOpacity underlayColor="red"
onPress={pressHandlerMapTest}
onPressIn={() => {
localStorage.setItem('tour', 'others');
}}>
<Image source={require("../assets/royals.png")} ></Image>
</TouchableOpacity>
</View>
</ImageBackground>
);
const pressHandlerMapTest = () => {
localStorage.setItem('tour', 'others');
navigation.navigate("TestMapScreen");
};
return (
<ImageBackground style={styles.background}>
<View style={styles.tourWindow}>
<TouchableOpacity underlayColor="red"
onPress={pressHandlerMapTest}
>
<Image source={require("../assets/royals.png")} ></Image>
</TouchableOpacity>
</View>
</ImageBackground>
);

How to pass data item to react native modal

I am trying to pass data item to a react native modal on a click of a button 'view modal' but it seems I am missing something in my code.
Here is the data object that is been looped to show on the timeline screen
Object {
"farmer_id": "4",
"farmer_name": "Joshua Adebisi",
"id": "4",
"product_description": "The grains of rice is good for healthy.It is durable,I
t is Awesome Intesrest buyers can contact via contact 08073047104.",
"product_image": "https://via.placeholder.com/600/cb47e2",
"product_name": "5kg Grains of Rice",
"profile_img": "https://via.placeholder.com/150/cb47e2",
"uploaded_time": "2019-06-10 23:48:04",
}
Object {
"farmer_id": "3",
"farmer_name": "Omolewa Stephen",
"id": "3",
"product_description": "The grains of rice is good for healthy.It is durable,I
t is Awesome Intesrest buyers can contact via contact 08073047104.",
"product_image": "https://via.placeholder.com/600/4dcdf6",
"product_name": "5kg Grains of Rice",
"profile_img": "https://via.placeholder.com/150/cb47e2",
"uploaded_time": "2019-06-10 23:48:04",
}
Object {
"farmer_id": "2",
"farmer_name": "Salami Paul",
"id": "2",
"product_description": "The grains of rice is good for healthy.It is durable,I
t is Awesome Intesrest buyers can contact via contact 08073047104.",
"product_image": "https://via.placeholder.com/600/cb47e2",
"product_name": "5kg Grains of Rice",
"profile_img": "https://via.placeholder.com/150/cb47e2",
"uploaded_time": "2019-06-10 23:48:04",
}
Object {
"farmer_id": "1",
"farmer_name": "Adebiyi Samuel",
"id": "1",
"product_description": "The grains of rice is good for healthy.It is durable,T
he grains of rice is good for healthy.It is durable.It is Awesome Intesrest buye
rs can contact via contact 08073047104.
",
"product_image": "https://via.placeholder.com/600/4dcdf6",
"product_name": "5kg Grains of Beans",
"profile_img": "https://via.placeholder.com/150/cb47e2",
"uploaded_time": "2019-06-11 02:56:53",
}
Here is the timeline code
import React, {Component} from 'react';
import {TextInput,Modal,Alert,TouchableHighlight,StyleSheet,RefreshControl ,ScrollView,Dimensions,Image,StatusBar,ActivityIndicator,Text, View,TouchableOpacity,KeyboardAvoidingView} from 'react-native';
import { createBottomTabNavigator,createStackNavigator,createSwitchNavigator, createAppContainer} from "react-navigation";
let {height, width} = Dimensions.get('window');
import { Ionicons } from '#expo/vector-icons';
import { Font } from 'expo';
import { AsyncStorage } from 'react-native';
export default class Timeline extends Component {
constructor(props){
super(props)
console.log(props)
this.state = {
username: '',
photo: '',
email: '',
userId: '',
address: '',
timeline: [],
modalVisible: false,
refreshing: false
}
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
Home = () => {
alert("Home");
}
PostTimeline = () => {
return fetch( "http://texotrack.com/api/user/timeline.php", {
method: "POST",
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'fetch'
})
}).then((response) => response.json()).then((responseJsonFromServer) => {
this.setState({
timeline: responseJsonFromServer
});
})
}
componentDidMount(){
this.PostTimeline();
AsyncStorage.getItem("key").then((data) =>{
const val = JSON.parse(data);
this.setState({
username: data.name,
photo: data.photo,
email: data.email,
userId: data.id,
address: data.address
})
})
}
render() {
const timeLineList = this.state.timeline.map((data) => {
console.log(data);
const thumbnail = data.profile_img;
const product_image = data.product_image;
return (
<View elevation={5} key={data.id} style={styles.card}>
<Modal
animationType="fade"
transparent={false}
visible={this.state.modalVisible}
key={data.id}
onRequestClose={() => {
alert('Modal has been closed.');
}}>
<View style={{margin: 10}}>
<Text style={styles.headerText}>Product details: {data.product_name}</Text>
<View style={styles.cardheader}>
<View style={styles.miniheader}>
<Image style={styles.thumbnail} source={{uri: thumbnail}} />
<Text style={styles.thumb_name}>{data.farmer_name}</Text>
</View>
<Text style={styles.timestamp}>{data.uploaded_time}</Text>
</View>
<View style={styles.cardbody}>
<Image style={styles.cardbody_image} source={{uri: product_image}}/>
<Text style={styles.p_name}>{data.product_name}</Text>
<Text style={styles.p_desc}>{data.product_description}</Text>
<View>
</View>
</View>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text>Close</Text>
</TouchableHighlight>
</View>
</Modal>
<View style={styles.cardheader}>
<View style={styles.miniheader}>
<Image style={styles.thumbnail} source={{uri: thumbnail}} />
<Text style={styles.thumb_name}>{data.farmer_name}</Text>
</View>
<Text style={styles.timestamp}>{data.uploaded_time}</Text>
</View>
<View style={styles.cardbody}>
<Image style={styles.cardbody_image} source={{uri: product_image}}/>
<Text style={styles.p_name}>{data.product_name}</Text>
<Text style={styles.p_desc}>{data.product_description}</Text>
<View>
<TouchableOpacity
onPress={() => {
this.setModalVisible(true);
}} style={styles.buttonContainer}>
<Text style={styles.buttonText}>Show Modal</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
});
return (
<View style={styles.container}>
<View elevation={5} style={styles.mainheader}>
<Text style={styles.iconTop} onPress={() => this.PostTimeline()}>
<Ionicons name="md-refresh" size={32} color="black" />
</Text>
<Text style={styles.headerTitle}>Home</Text>
<Text style={styles.iconTop} onPress={() => this.Home()}>
<Ionicons name="md-home" size={32} color="black" />
</Text>
</View>
<View style={styles.content}>
<View style={{padding: 10}}>
<Text style={styles.headerText}><Ionicons name="md-cart" size={26} color="black" /> Marketplace</Text>
</View>
<View style={{flex:1}}>
<ScrollView alwaysBounceVertical={true} contentContainerStyle={{ flexGrow: 1}} enabled bounces={true}>
{timeLineList}
</ScrollView>
</View>
</View>
</View>
);
}
}
The focus is on the render method here with the modal, how do I pass the data item to the modal when each button is clicked to view the details. Thanks
render() {
const timeLineList = this.state.timeline.map((data) => {
console.log(data);
const thumbnail = data.profile_img;
const product_image = data.product_image;
return (
<View elevation={5} key={data.id} style={styles.card}>
<Modal
animationType="fade"
transparent={false}
visible={this.state.modalVisible}
key={data.id}
onRequestClose={() => {
alert('Modal has been closed.');
}}>
<View style={{margin: 10}}>
<Text style={styles.headerText}>Product details: {data.product_name}</Text>
<View style={styles.cardheader}>
<View style={styles.miniheader}>
<Image style={styles.thumbnail} source={{uri: thumbnail}} />
<Text style={styles.thumb_name}>{data.farmer_name}</Text>
</View>
<Text style={styles.timestamp}>{data.uploaded_time}</Text>
</View>
<View style={styles.cardbody}>
<Image style={styles.cardbody_image} source={{uri: product_image}}/>
<Text style={styles.p_name}>{data.product_name}</Text>
<Text style={styles.p_desc}>{data.product_description}</Text>
<View>
</View>
</View>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text>Close</Text>
</TouchableHighlight>
</View>
</Modal>
<View style={styles.cardheader}>
<View style={styles.miniheader}>
<Image style={styles.thumbnail} source={{uri: thumbnail}} />
<Text style={styles.thumb_name}>{data.farmer_name}</Text>
</View>
<Text style={styles.timestamp}>{data.uploaded_time}</Text>
</View>
<View style={styles.cardbody}>
<Image style={styles.cardbody_image} source={{uri: product_image}}/>
<Text style={styles.p_name}>{data.product_name}</Text>
<Text style={styles.p_desc}>{data.product_description}</Text>
<View>
<TouchableOpacity
onPress={() => {
this.setModalVisible(true);
}} style={styles.buttonContainer}>
<Text style={styles.buttonText}>Show Modal</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
});
return (
<View style={styles.container}>
<View elevation={5} style={styles.mainheader}>
<Text style={styles.iconTop} onPress={() => this.PostTimeline()}>
<Ionicons name="md-refresh" size={32} color="black" />
</Text>
<Text style={styles.headerTitle}>Home</Text>
<Text style={styles.iconTop} onPress={() => this.Home()}>
<Ionicons name="md-home" size={32} color="black" />
</Text>
</View>
<View style={styles.content}>
<View style={{padding: 10}}>
<Text style={styles.headerText}><Ionicons name="md-cart" size={26} color="black" /> Marketplace</Text>
</View>
<View style={{flex:1}}>
<ScrollView alwaysBounceVertical={true} contentContainerStyle={{ flexGrow: 1}} enabled bounces={true}>
{timeLineList}
</ScrollView>
</View>
</View>
</View>
);
}
And if there is a better way to refactor this code, I am open to learning. Thanks
I have quickly changed your code to give you the idea of how this could work checkout below this should work.
No need to loop the modal set the data to the state when button is pressed and modal can read the data from the state.
import React, {Component} from 'react';
import {TextInput,Modal,Alert,TouchableHighlight,StyleSheet,RefreshControl ,ScrollView,Dimensions,Image,StatusBar,ActivityIndicator,Text, View,TouchableOpacity,KeyboardAvoidingView} from 'react-native';
import { createBottomTabNavigator,createStackNavigator,createSwitchNavigator, createAppContainer} from "react-navigation";
let {height, width} = Dimensions.get('window');
import { Ionicons } from '#expo/vector-icons';
import { AsyncStorage } from 'react-native';
export default class Timeline extends Component {
constructor(props){
super(props)
console.log(props)
this.state = {
username: '',
photo: '',
email: '',
userId: '',
address: '',
timeline: [],
modalVisible: false,
refreshing: false,
selectedData: [],
}
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
Home = () => {
alert("Home");
}
PostTimeline = () => {
return fetch( "http://texotrack.com/api/user/timeline.php", {
method: "POST",
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'fetch'
})
}).then((response) => response.json()).then((responseJsonFromServer) => {
this.setState({
timeline: responseJsonFromServer
});
})
}
componentDidMount(){
this.PostTimeline();
AsyncStorage.getItem("key").then((data) =>{
const val = JSON.parse(data);
this.setState({
username: data.name,
photo: data.photo,
email: data.email,
userId: data.id,
address: data.address
})
})
}
_selectedItem = (data) => {
this.setState({selectedData: data});
this.setModalVisible(true);
}
render() {
const data = this.state.selectedData
const timeLineList = this.state.timeline.map((data) => {
console.log(data);
const thumbnail = data.profile_img;
const product_image = data.product_image;
return (
<View elevation={5} key={data.id} style={styles.card}>
<View style={styles.cardheader}>
<View style={styles.miniheader}>
<Image style={styles.thumbnail} source={{uri: thumbnail}} />
<Text style={styles.thumb_name}>{data.farmer_name}</Text>
</View>
<Text style={styles.timestamp}>{data.uploaded_time}</Text>
</View>
<View style={styles.cardbody}>
<Image style={styles.cardbody_image} source={{uri: product_image}}/>
<Text style={styles.p_name}>{data.product_name}</Text>
<Text style={styles.p_desc}>{data.product_description}</Text>
<View>
<TouchableOpacity
onPress={() => {
this._selectedItem(data);
}} style={styles.buttonContainer}>
<Text style={styles.buttonText}>Show Modal</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
});
return (
<View style={styles.container}>
<View elevation={5} style={styles.mainheader}>
<Text style={styles.iconTop} onPress={() => this.PostTimeline()}>
<Ionicons name="md-refresh" size={32} color="black" />
</Text>
<Text style={styles.headerTitle}>Home</Text>
<Text style={styles.iconTop} onPress={() => this.Home()}>
<Ionicons name="md-home" size={32} color="black" />
</Text>
</View>
<View style={styles.content}>
<View style={{padding: 10}}>
<Text style={styles.headerText}><Ionicons name="md-cart" size={26} color="black" /> Marketplace</Text>
</View>
<View style={{flex:1}}>
<ScrollView alwaysBounceVertical={true} contentContainerStyle={{ flexGrow: 1}} enabled bounces={true}>
{timeLineList}
</ScrollView>
</View>
</View>
<Modal
animationType="fade"
transparent={false}
visible={this.state.modalVisible}
key={data.id}
onRequestClose={() => {
alert('Modal has been closed.');
}}>
<View style={{margin: 10}}>
<Text style={styles.headerText}>Product details: {data.product_name}</Text>
<View style={styles.cardheader}>
<View style={styles.miniheader}>
<Image style={styles.thumbnail} source={{uri: data.thumbnail}} />
<Text style={styles.thumb_name}>{data.farmer_name}</Text>
</View>
<Text style={styles.timestamp}>{data.uploaded_time}</Text>
</View>
<View style={styles.cardbody}>
<Image style={styles.cardbody_image} source={{uri: data.product_image}}/>
<Text style={styles.p_name}>{data.product_name}</Text>
<Text style={styles.p_desc}>{data.product_description}</Text>
<View>
</View>
</View>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text>Close</Text>
</TouchableHighlight>
</View>
</Modal>
</View>
);
}
}

scrollview insde flatlist not scrolling

i have this flatlist in render():
render() {
return (
<FlatList
ref='listRef'
data={this.props.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
/>
)
}
Then inside renderItem() i have:
return (
<View style={{flex:1}}>
<ScrollView style={{flex:1}}>
{item.mascotas.map(function(d, index){
return (
<View key={index} style={{flex:1}}>
<Image source={require('./img/base-face-image.png')} style={styles.mascotas_list_item_img} />
<View style={styles.mascotas_list_item_details}>
<Text style={styles.mascotas_list_item_details_name}>{d.nombre}</Text>
</View>
</View>
)
})}
</ScrollView>
</View>
As you can see the parent view and its childs have flex:1, i've also tried adding flex:1 to FlatList but doesn't work neither. I need the scrollview to scroll.

Categories

Resources