React native Flatlist error requires all the attributes - react-native

I am new to react native. I am doing a simple app where I add name and age of a person to firebase and then showing it in the list, I am using flatList in this project but it asks to import all the attributes of the flatList. if I add only 2 attributes like data, renderItem it gives an error, please help
here my code
import React from "react";
import {StyleSheet, View, Button, Text, FlatList, TextInput, ListView} from "react-native";
import firebase from './firebase'
let db = firebase.firestore();
class TextInputExample extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
userName: '',
userAge: '',
input1Background: 'red',
textColor1: 'white',
input2Background: 'red',
textColor2: 'white'
};
}
componentDidMount(): void {
db.collection('users')
.onSnapshot((snapshot) => {
snapshot.docChanges().forEach(change => {
if (change.type === 'added') {
this.state.data.push({
name: change.doc.get('name'),
age: change.doc.get('age')
});
console.log(this.state.data);
}
})
}, (error => {
console.log(error.message);
}))
}
addToDatabase = () => {
let data = {
name: this.state.userName,
age: this.state.userAge
};
console.log(data);
db.collection('users').add(data)
.then(ref => {
}).catch(msg => {
console.log(msg);
});
};
renderItem = ({item}) => {
return(
<View>
<Text>{item.name}</Text>
<Text>{item.age}</Text>
</View>
);
};
render(): React.Node {
return (
<View style={styles.container}>
<TextInput
placeHolder={'Enter name'}
onChangeText={(text) => this.setState( {userName: text} )}
/>
<TextInput
placeHolder={'Enter Age'}
onChangeText={(text) => this.setState( {userAge: text} )}
/>
<Button title={'Add'} onPress={() => this.addToDatabase()}/>
<View>
<FlatList
data={this.state.data}
renderItem={this.renderItem}
/>
</View>
</View>
);
}
}
export default TextInputExample;
const styles = StyleSheet.create({
container: {
flex: 1, alignSelf: 'center', alignItems: 'center'
}
});

I think your error is because you're updating your state in the wrong way, if you want to add an element to an array in your state you must do it using the setState method and not directly accessing to the array and push it.
Do this
const newItem = {
name: change.doc.get('name'),
age: change.doc.get('age')
}
this.setState((prevState) => ({
...prevState,
data: [...prevState, newItem]
}))

Related

Error in Navigating Screen using Button props in React Native

I've been trying some codes for the navigation in react native, I want to navigate from Listlab screen to FormScreen for updating which mean I want to navigate the screen and pass the value to new screen and its textfield. But when I tried, it shown me an error that I already tried to solve it for many times. Can you help me to solve this error, thank you :D
Here's The Error Message:
And Here's my Listlab Code:
import React, { Component } from 'react';
import { View, Text, StyleSheet, Platform, StatusBar} from 'react-native';
import PropTypes from 'prop-types';
import { Card, CardTitle, CardContent, CardAction, CardButton, CardImage } from 'react-native-material-cards'
import { CardItem } from 'native-base';
import { ScrollView } from 'react-native-gesture-handler';
import { createAppContainer } from 'react-navigation';
import {createStackNavigator } from 'react-navigation-stack';
import Button from 'react-native-button';
import { withNavigation } from 'react-navigation';
class ListLab extends Component {
_OnButtonPress(no_pengajuan) {
Alert.alert(no_pengajuan.toString());
}
handleDelete(id){
let url = "http://URL:8000/api/pinjams/"+id ;
// let data = this.state;
fetch(url,{
method:'DELETE',
headers:{
"Content-Type" : "application/json",
"Accept" : "application/json"
},
})
.then((result) => {
result.json().then((resp) => {
console.warn("resp", resp)
alert("Data is Removed")
})
})
}
render() {
this._OnButtonPress = this._OnButtonPress.bind(this);
return (
<View style={styles.pinjamList}>
<StatusBar hidden />
{this.props.pinjams.map((pinjam) => {
return (
<View key={pinjam.id}>
{/* Baru nambah data */}
<Card>
<CardImage
source={{uri: 'http://www.rset.edu.in/pages/uploads/images/computerLab-img1.jpg'}}
title={pinjam.lab }
/>
<CardTitle
title={ pinjam.ketua_kegiatan }
subtitle={ pinjam.keperluan }
/>
<CardContent><Text>{ pinjam.tanggal_mulai} - {pinjam.tanggal_selesai }</Text></CardContent>
<CardContent><Text>{ pinjam.jam_mulai } - {pinjam.jam_selesai }</Text></CardContent>
</Card>
<Button
style={{fontSize:20, color:'red'}}
styleDisabled={{color:'grey'}}
onPress ={()=>{this.handleDelete(pinjam.id)}}
> {"\n"} Delete
</Button>
<Button
style={{fontSize:20, color:'green'}}
styleDisabled={{color:'grey'}}
onPress ={()=>{this.props.navigation.navigate('FormScreen')}}
> {"\n"} Update
</Button>
</View>
)
})}
</View>
);
}
}
const styles = StyleSheet.create({
pinjamList: {
flex: 1,
flexDirection: 'column',
justifyContent: 'space-around',
},
pinjamtext: {
fontSize: 14,
fontWeight: 'bold',
textAlign: 'center',
}
});
export default withNavigation(ListLab);
And This one is my FormScreen Code:
import React , { Component } from 'react';
import {
ScrollView,
View,
Text,
StyleSheet,
StatusBar
} from 'react-native';
import { Header, Left, Right, Icon, Footer, Label} from 'native-base';
import Button from 'react-native-button';
import t from 'tcomb-form-native';
import { Dropdown } from 'react-native-material-dropdown';
import { TextField } from 'react-native-material-textfield';
import DatePicker from 'react-native-datepicker';
import moment from 'moment';
class FormScreens extends Component {
static navigationOptions = {
drawerIcon : ({tintColor})=>(
<Icon name="paper" style={{ fontSize: 24, color: tintColor }}/>
)
}
constructor(){
super();
this.state = {
ketua_kegiatan: '',
lab: '',
level: '',
tanggal_mulai: '',
tanggal_selesai: '',
jam_mulai: '',
jam_selesai: '',
daftar_nama: '',
keperluan: '',
kontak_ketua:'',
dosen_pembina: '',
app_laboran: '',
app_kalab: '',
app_kajur: '',
app_pudir: '',
}
}
submit(id){
let url = "http://URL:8000/api/pinjams"+id;
let data = this.state;
fetch(url,{
method:'PUT',
headers:{
"Content-Type" : "application/json",
"Accept" : "application/json"
},
body: JSON.stringify(data)
})
.then((result) => {
result.json().then((resp) => {
console.warn("resp", resp)
alert("Data is Updated")
})
})
}
render() {
let lab = [{
value: '313',
}, {
value: '316',
}, {
value: '317',
}, {
value: '318',
}, {
value: '319',
}, {
value: '320',
}, {
value: '324',
}, {
value: '325',
}, {
value: '329',
}, {
value: '330',
}, {
value: '234',
}, {
value: '283',
}, {
value: '218',
}, {
value: '224',
}, {
value: '225',
}, {
value: '230',
}, {
value: '233',
}, {
value: '135',
}, {
value: '136',
}, {
value: '137',
}, {
value: 'Workshop',
}, {
value: 'Lab Bahasa',
}];
let level = [{
value: 1,
}, {
value: 2,
}, {
value: 3,
}];
return (
//08-08-2019 (Ubah view menjadi ScrollView)
<ScrollView style={styles.container}>
<StatusBar hidden />
<Header style={{backgroundColor:'orange', flex:0.8}}>
<Left style={{justifyContent:"flex-start",flex:1,marginTop:5}}>
<Icon name="menu" onPress={()=>this.props.navigation.openDrawer()} />
</Left>
</Header>
<View style={{padding:20}}>
<Text style={{fontSize:20,textAlign: 'center',paddingLeft:20,fontWeight: 'bold'}}>{"\n"}Halaman Pengajuan</Text>
<TextField
label = 'ketua_kegiatan'
// value = {ketua_kegiatan}
onChangeText={ (ketua_kegiatan) => this.setState({ ketua_kegiatan }) }
// onChange={(data) => { this.setState({ketua_kegiatan:data.target.value}) }}
value = {this.state.ketua_kegiatan}
/>
<Dropdown
label='Laboratorium'
data={lab}
onChangeText={ (lab) => this.setState({ lab }) }
/>
<Dropdown
label='Level'
data={level}
onChangeText={ (level) => this.setState({ level }) }
/>
<TextField
label = 'Tanggal Mulai'
// value = {tanggal_mulai}
onChangeText={ (tanggal_mulai) => this.setState({ tanggal_mulai }) }
// onChange={(data) => { this.setState({tanggal_mulai:data.target.value}) }}
value = {this.state.tanggal_mulai}
/>
<TextField
label = 'Tanggal Selesai'
// value = {tanggal_selesai}
onChangeText={ (tanggal_selesai) => this.setState({ tanggal_selesai }) }
// onChange={(data) => { this.setState({tanggal_selesai:data.target.value}) }}
value = {this.state.tanggal_selesai}
/>
<TextField
label = 'Jam Mulai'
// value = {jam_mulai}
onChangeText={ (jam_mulai) => this.setState({ jam_mulai }) }
// onChange={(data) => { this.setState({jam_mulai:data.target.value}) }}
value = {this.state.jam_mulai}
/>
<TextField
label = 'Jam Selesai'
// value = {jam_selesai}
onChangeText={ (jam_selesai) => this.setState({ jam_selesai }) }
// onChange={(data) => { this.setState({jam_selesai:data.target.value}) }}
value = {this.state.jam_selesai}
/>
<TextField
label = 'Keperluan'
// value = {keperluan}
onChangeText={ (keperluan) => this.setState({ keperluan }) }
// onChange={(data) => { this.setState({keperluan:data.target.value}) }}
value = {this.state.keperluan}
/>
<TextField
label = 'Daftar Nama'
// value = {daftar_nama}
onChangeText={ (daftar_nama) => this.setState({ daftar_nama }) }
// onChange={(data) => { this.setState({daftar_nama:data.target.value}) }}
value = {this.state.daftar_nama}
/>
<TextField
label = 'kontak_ketua'
// value = {kontak_ketua}
onChangeText={ (kontak_ketua) => this.setState({ kontak_ketua }) }
// onChange={(data) => { this.setState({kontak_ketua:data.target.value}) }}
value = {this.state.kontak_ketua}
/>
<TextField
label = 'Dosen Pembina'
// value = {dosen_pembina}
onChangeText={ (dosen_pembina) => this.setState({ dosen_pembina }) }
// onChange={(data) => { this.setState({dosen_pembina:data.target.value}) }}
value = {this.state.dosen_pembina}
/>
<TextField
label = 'app_laboran'
// value = {app_laboran}
onChangeText={ (app_laboran) => this.setState({ app_laboran }) }
// onChange={(data) => { this.setState({app_laboran:data.target.value}) }}
value = {this.state.app_laboran}
/>
<Button
style={{fontSize:20, color:'orange'}}
styleDisabled={{color:'grey'}}
onPress ={()=>{this.submit(pinjam.id)}}
> {"\n"} Submit
</Button>
</View>
{/* <Form type={Pengajuan}/> */}
<Footer style={{backgroundColor:'white'}}>
<Text style={{paddingTop:10,color:'grey'}}>{"\n"}Copyright reserved to #Leony_vw</Text>
</Footer>
</ScrollView>
);
}
}
export default FormScreens;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
// ...Platform.select({
// android: {
// marginTop: StatusBar.currentHeight
// }
// })
},
});
Here's my App.js:
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView,ScrollView, Dimensions, Image } from 'react-native';
import { createDrawerNavigator, DrawerItems, createAppContainer } from 'react-navigation';
// import HomeScreen from './screens/HomeScreen';
// import FormScreen from './screens/FormScreen';
// import SigninScreen from './screens/SigninScreen';
import HomeScreen from './screens/laboran/HomeScreen';
import FormScreen from './screens/laboran/FormScreen';
import * as firebase from "firebase";
const { width } = Dimensions.get('window');
var firebaseConfig = {
apiKey: "XXXXXX",
authDomain: "XXXXX",
databaseURL: "XXXXX",
projectId: "XXXXX",
storageBucket: "XXXXX",
messagingSenderId: "XXXXX",
appId: "XXXXX"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default class App extends React.Component{
render() {
return (
<Apps/>
);
}
}
const CustomDrawerComponent = (props) => (
<SafeAreaView style={{ flex:1 }}>
<View style={{height:150, backgroundColor: 'white', alignItems :'center', justifyContent:'center'}}>
<Image source={require('./assets/up2.png')} style={{height:50, width:50,borderRadius:35 }}/>
</View>
<ScrollView>
<DrawerItems {...props}/>
</ScrollView>
</SafeAreaView>
)
const AppDrawerNavigator = createDrawerNavigator({
// Login:SigninScreen,
Home:HomeScreen,
Form:FormScreen
}, {
contentComponent: CustomDrawerComponent,
drawerWidth: width,
contentOptions:{
activeTintColor:'orange'
}
})
const Apps = createAppContainer(AppDrawerNavigator)
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
That is probably because Listlab is rendered by a component that is actually a screen.
For example, let say your FormScreen would render the Listlab component. FormScreen has access to the navigation prop, but Listlab does not.
You have 2 solutions:
- pass the navigation prop to Listlab
- use the withNavigation HOC
I found the solution last night, I think I can's just navigate from ListLab because ListLab is just like a child screen of HomeScreen. When I try it on HomeScreen, the prop is doing fine, and it can navigate to my FormScreen tho. And also, I think I did call the wrong alias of FormScreen in App.js and that's the problem as well. But now, I would like to put the button and the navigation in ListLab, I still wonder how can I navigate using button in child screen. But thanks guys for helping me :D Cheers!

React native navigation with redux

I have an inbox component which fetches all the notifications from the server and lists in a view. The code for which looks like,
import React, { Component } from 'react'
import {
View,
FlatList,
ActivityIndicator,
TouchableOpacity
} from 'react-native'
import {List, ListItem, SearchBar} from 'react-native-elements'
import Header from '../common/Header'
import { Container } from 'native-base'
import PushNotifications from '../../fcm/notifications/PushNotifications'
import NotificationDetails from './NotificationDetails';
export const Navigator = new StackNavigator({
NotificationList: { screen: NotificationList },
NotificationDetail: { screen: NotificationDetail },
},{
initialRouteName: 'NotificationList',
})
class NotificationList extends Component {
constructor(props) {
super(props)
this.state = {
loading: false,
data: [],
page: 1,
seed: 1,
error: null,
refreshing: false
}
this.loadNotificationDetails = this.loadNotificationDetails.bind(this)
}
componentDidMount() {
const{dispatch,actions} = this.props
dispatch(actions.getNotification())
}
handleRefresh = () => {
this.setState(
{
page: 1,
seed: this.state.seed + 1,
refreshing: true
},
() => {
const{dispatch,actions} = this.props
dispatch(actions.getNotification())
}
)
}
handleLoadMore = () => {
this.setState(
{
page: this.state.page + 1
},
() => {
const{dispatch,actions} = this.props
dispatch(actions.getNotification())
}
);
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
marginLeft: "14%"
}}
/>
);
};
renderHeader = () => {
return <SearchBar placeholder="Type Here..." lightTheme round />
}
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
borderColor: "#CED0CE"
}}
>
<ActivityIndicator animating size="large" />
</View>
)
}
loadNotificationDetails = () => {
this.props.navigation.navigate('NotificationDetails')
}
render() {
return (
<Container >
<Header />
<List containerStyle={{ marginTop: 0, borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
data={this.props.listNotification}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => this.loadNotificationDetails()}>
<ListItem
roundAvatar
title={`${item.text}`}
subtitle={item.dateTime}
// avatar={{ uri: item.picture.thumbnail }}
containerStyle={{ borderBottomWidth: 0 }}
/>
</TouchableOpacity>
)}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
onRefresh={this.handleRefresh}
refreshing={this.state.refreshing}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={50}
/>
</List>
<PushNotifications />
</Container>
)
}
}
export default NotificationList;
Now what i want to achieve is on clicking any of the listItem, i want to load the complete detailed notification.
Whats happening is when i click it seems to be missing the navigation object. Hence its complaining cannot find property of navigate.
The props is having only the items from the redux store, i am not able to understand how do i get the navigation props into this component which is already having props from the redux store?
How do i achieve this? Any help is much appreciated.
Thanks,
Vikram
StackNavigator is a factory function instead of a constructor. Have you try
const Navigator = StackNavigator({
NotificationList: { screen: NotificationList },
NotificationDetail: { screen: NotificationDetail },
},{
initialRouteName: 'NotificationList',
})
It is a bit confusing, however in v2 the team change the api to createStackNavigator.

how can I navigate from LoginForm.js to product.js after successfull login

how to navigate from LoginForm.js to product.js ?
route.js
import React from 'react';
import { StyleSheet,View,Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
import Home from './pages/home';
import Products from './pages/product';
// import Products from './pages/components/LoginForm';
const navigation = StackNavigator({
Home : { screen: Home },
// Login : { screen: LoginForm },
Products : { screen: Products },
});
export default navigation;
home.js
import React from 'react';
import { StyleSheet, Text, View, Button, StatusBar, Image } from 'react-native';
import LoginForm from './components/LoginForm';
export default class Home extends React.Component {
static navigationOptions = {
header: null
};
render() {
return (
<View style = { styles.container }>
<StatusBar
backgroundColor="#007ac1" barStyle="light-content"/>
<View style= { styles.logoContainer }>
<Image style = {styles.logo} source={require('../images/logo.png')} />
</View>
<View style= { styles.formContainer }>
<LoginForm />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#03a9f4'
},
logoContainer: {
flexGrow: 1, justifyContent:'center', alignItems:'center'
},
logo: {
width: 80, height: 80
},
formContainer: {
}
});
LoginForm.js
import React from 'react';
import { StyleSheet, Text, View ,TextInput, TouchableOpacity } from 'react-native';
export default class LoginForm extends React.Component {
constructor(props){
super(props)
this.state={
userName:'',
password:'',
type:'A'
}
}
userLogin = () =>{
const { userName } = this.state;
const { password } = this.state;
const { type } = this.state;
fetch('http://192.168.0.4:3000/notes',{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body:JSON.stringify({
userName : userName,
password : password,
type : type
})
})
.then((response)=> response.json())
.then((responseJson) => {
if(responseJson.response.success == true) {
// alert(responseJson.response.result);
navigate('Products');
}else{
alert(responseJson.response.result);
}
})
.catch((error)=>{
console.error(error);
})
}
render() {
return (
<View style = {styles.container}>
<TextInput
underlineColorAndroid="transparent"
placeholder="Username or Email"
placeholderTextColor = "rgba(255,255,255,0.7)"
returnKeyType="next"
onSubmitEditing={() => this.passwordInput.focus()}
onChangeText = {userName => this.setState({userName})}
style={styles.input} />
<TextInput
placeholder="Password"
underlineColorAndroid="transparent"
secureTextEntry
returnKeyType="go"
placeholderTextColor = "rgba(255,255,255,0.7)"
ref = {(input) => this.passwordInput = input}
onChangeText = {password => this.setState({password})}
style={styles.input} />
<TouchableOpacity style={styles.buttonContainer} onPress={this.userLogin} >
<Text style={styles.buttonText}>LOGIN</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
container : {
padding:20
},
input: {
height:40, backgroundColor: 'rgba(255,255,255,0.2)', marginBottom:20,
color:'#FFF', paddingHorizontal:10, borderRadius:5
},
buttonContainer: {
backgroundColor: "#2980b9", paddingVertical:10, borderRadius:5
},
buttonText: {
textAlign :'center', color:'#FFFFFF', fontWeight:'700'
}
});
product.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default class Product extends React.Component {
static navigationOptions = {
// title: 'Home',
header: null
};
render() {
return (
<View style = { styles.container }>
<Text> Product Page open </Text>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Make LoginForm as part of navigator (it is currently commented). Then inside the userLogin function use this.props.navigation.navigate('Products') to navigate, take a look at the navigation doc
userLogin = () =>{
...
fetch('http://192.168.0.4:3000/notes',{
...
})
.then((response)=> response.json())
.then((responseJson) => {
if(responseJson.response.success == true) {
// alert(responseJson.response.result);
this.props.navigation.navigate('Products');
}else{
alert(responseJson.response.result);
}
})
.catch((error)=>{
console.error(error);
})
}
Hope this will help!

State does not change until the second button press? Adding a call back throws an error "invariant violation: invalid argument passed"

I'm trying to render a Flatlist that contains a store name. Upon clicking the store name, more information about the store should be displayed.
I attempted to change state and then use
{this.renderMoreDetails(item) && this.state.moreDetailsShown}
to get the additional information to appear. However, it was clear via console.log that state was only changed after a second button press.
From what I read in this article 1 and this article 2 it seemed as though I needed a callback function as an additional parameter to my setState().
I tried adding a callback function(probably incorrect, but I'm extremely lost at this point) and only got more errors.
I know that I have access to all of the data from renderItem inside FlatList. How do I make it appear upon click?
import React, { Component } from 'react';
import {
View,
FlatList,
Text,
TouchableWithoutFeedback,
ListView,
ScrollView
} from 'react-native'
import { NavigationActions } from 'react-navigation';
import { Header, Card, CardSection } from '../common';
import Config from '../Config';
export default class Costco extends Component<Props> {
constructor(props) {
super(props);
this.state = {
stores: [],
selectedItem: {id: null},
};
}
componentWillMount() {
const obj = Config.costcoThree;
const costcoArr = Object.values(obj);
this.setState({
stores: costcoArr,
})
}
renderListOfStores() {
return <FlatList
data={this.state.stores}
renderItem={ ({item}) => this.singleStore(item)}
keyExtractor={(item) => item.id}
extraData={this.state.selectedItem} />
}
singleStore(item) {
console.log(this.state.selectedItem.id)
return item.id === this.state.selectedItem.id ?
<TouchableWithoutFeedback
onPress={() => this.selectStore(item)}
>
<View>
<Text>{item.branchName}</Text>
<Text>Opening Time {item.openingTime}</Text>
<Text>Closing Time {item.closingTime}</Text>
<Text>Address {item.dongAddKor}</Text>
</View>
</TouchableWithoutFeedback>
:
<TouchableWithoutFeedback>
<View>
<Text>{item.branchName}</Text>
<Text>Only showing second part</Text>
</View>
</TouchableWithoutFeedback>
}
selectStore(item) {
this.setState({selectedItem: item});
console.log('repssed');
}
render() {
return(
<ScrollView>
<Header headerText="Costco"/>
<Text>hello</Text>
{this.renderListOfStores()}
</ScrollView>
)
}
}
as a workaround you can have a state that maintain your selected item to expand(or something like another view) and then you can use some conditions to work for render your flat list data.
Consider the below code and let me know if you need some more clarification.
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,FlatList,TouchableNativeFeedback,
View
} from 'react-native';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
response: [],
selectedItem: {id: null},
};
}
userListLayout() {
const {response} = this.state;
return <FlatList data={response} renderItem={ ({item}) => this.singleUserLayout(item)} keyExtractor={(item) => item.email} extraData={this.state.selectedItem} />
}
singleUserLayout(item) {
return item.id == this.state.selectedItem.id ?
<TouchableNativeFeedback onPress={() => this.userSelected(item)}>
<View style={{flex:1, borderColor: 'black', borderWidth: 1}}>
<Text style={{padding: 10, fontSize: 25}}>{item.email}</Text>
<Text style={{padding: 10,fontSize: 20}}>{item.name}</Text>
</View>
</TouchableNativeFeedback>
: <TouchableNativeFeedback onPress={() => this.userSelected(item)}><Text style={{padding: 10,fontSize: 20}}>{item.email}</Text></TouchableNativeFeedback>
}
userSelected(item) {
console.log(item)
this.setState({selectedItem: item})
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then(data => data.json())
.then(response => this.setState({response}))
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>HI THERE</Text>
{this.userListLayout()}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

React Native Tab View _renderScene from another class

I try using Example React Native Tab View https://github.com/react-native-community/react-native-tab-view. I change on const FirstRoute to call from ListMahasiswa class, but there is error : FirstRoute(...) A Valid React element (or null) must be returned.
Main.js
import React, { PureComponent } from 'react';
import { View, StyleSheet } from 'react-native';
import { TabViewAnimated, TabBar, SceneMap } from 'react-native-tab-view';
import ListMahasiswa from './ListMahasiswa';
import InsertDataMhs from './InsertDataMhs';
import Coba from './Coba';
const FirstRoute = () => ListMahasiswa;
const SecondRoute = () => <View style={[ styles.container, { backgroundColor: '#673ab7' } ]} />;
export default class Main extends PureComponent {
state = {
index: 0,
routes: [
{ key: '1', title: 'First' },
{ key: '2', title: 'Second' },
],
};
_handleChangeTab = index => this.setState({ index });
_renderHeader = props => <TabBar {...props} />;
_renderScene = SceneMap({
'1': FirstRoute,
'2': SecondRoute,
});
render() {
return (
<TabViewAnimated
style={styles.container}
navigationState={this.state}
renderScene={this._renderScene}
renderHeader={this._renderHeader}
onRequestChangeTab={this._handleChangeTab}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
listMahasiswa.js
import React from 'react';
import {
AppRegistry,
Text,View,Button, ListView, Image, StyleSheet
} from 'react-native';
var URL="http://www.rey1024.com/api/getListMahasiswa.php";
export default class ListMahasiswa extends React.Component{
constructor(props){
super(props);
var ds = new
ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state={
dataSource: ds,
};
}
AmbilDataMahasiswa() {
fetch(URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows
(responseData),
});
}) .done();
}
render(){
this.AmbilDataMahasiswa();
return(
<View style={styles.mainContainer}>
<Text>Daftar Mahasiswa</Text>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
/>
</View>
);
}
renderRow(record){
return(
<View style={styles.row} >
<Text>{record.nim} {record.nama}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
mainContainer :{
flex:1,
backgroundColor:'#fff'
},
row :{
borderColor: '#f1f1f1',
borderBottomWidth: 1,
flexDirection: 'row',
marginLeft: 10,
marginRight: 10,
paddingTop: 20,
},
})
Have any solution? Thank you
ListMahasiswa in the following line is not a valid React element.
const FirstRoute = () => ListMahasiswa;
Try using jsx syntax instead:
const FirstRoute = () => <ListMahasiswa />;