How do I pass strings from one component to another component? - react-native

Login component:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight,
TextInput,
Image
} from 'react-native';
var DisplayData = require('./DisplayData');
export default class Login extends Component{
constructor(props){
super(props)
this.state = {
Latitude: '',
Longitude: '',
}
}
onPressDisplayData() {
this.props.navigator.push({
name: 'DisplayView',
component: DisplayData
});
}
render() {
return (
<View style = {styles.container}>
<Image source={require('./logo.png')}/>
<TextInput
style = {styles.input}
placeholder = 'Latitude'
autoCapitalize = 'none'
onChangeText={(text) => this.setState({Latitude:text})}
/>
<TextInput
style = {styles.input}
placeholder = 'Longitude'
autoCapitalize = 'none'
onChangeText={(text) => this.setState({Longitude:text})}
/>
<TouchableHighlight
style = {styles.submit}
onPress = {() => this.onPressDisplayData()
}
>
<Text>
Submit
</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create ({
container: {
flex: 1,
alignItems: 'center',
justifyContent:'center',
paddingBottom: 40
},
input: {
margin: 15,
height: 40,
borderColor: 'grey',
borderWidth: 1
},
submit: {
backgroundColor: '#FFDD03',
padding: 10
}
})
module.exports = Login;
DisplayData component:
import React, {
Component,
} from 'react';
import {
AppRegistry,
Image,
ListView,
StyleSheet,
Text,
View,
} from 'react-native';
var REQUEST_URL = 'http://api.geonames.org/earthquakesJSON?north='+4+'&south='+-9.9+'&east='+-22.4+'&west='+55.2+'&username=afdsanfd'
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
class DisplayData extends Component {
constructor(props){
super(props)
this.state = {
earthquakes: ds.cloneWithRows([])
};
}
componentDidMount() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => this.setState({ earthquakes: ds.cloneWithRows(responseData.earthquakes) }))
.catch(function(error) {
console.warn(error);
});
}
render() {
return (
<View>
<ListView
dataSource = {this.state.earthquakes}
renderRow={(rowData) => (
<View style={{flex: 1, paddingTop: 10, paddingBottom: 10, borderWidth: 0.5, paddingLeft: 10, borderColor: '#D3D3D3'}}>
<Text style={{fontSize: 25}}>{rowData.src}</Text>
<Text>DateTime: {rowData.datetime}</Text>
<Text>Magnitude: {rowData.magnitude}</Text>
<Text>EqID: {rowData.eqid}</Text>
<Text>Depth: {rowData.depth}</Text>
</View>
)}
/>
</View>
);
}
}
module.exports = DisplayData;
So what I am trying to accomplish through this app is having someone enter latitude and longitude such that an API call (REQUEST_URL) that'd return earthquake info. However, i'm struggling really hard with passing the entered latitude and longitude into the DisplayData component. I've tried things such as creating a global latitude and longitude but none have been working.

Related

Element type is invalid: expected a string with FlatList

Iam new to react-native, and are playing around with UI Kitten (https://akveo.github.io/react-native-ui-kitten/)
It has a default ChatListScreenBase that renders a list. It looks like this:
import React, {Component} from 'react';
import {
StyleSheet,
View,
ListView
} from 'react-native';
import ThemeService from '../util/ThemeService';
import api from '../util/ApiMock';
export default class ChatListScreenBase extends Component {
constructor(props) {
super(props);
let ds = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
let data = api.getUserMsgList(api.userId);
this.state = {
dataSource: ds.cloneWithRows(data)
};
}
render() {
let Header = ThemeService.getChatListHeaderComponent();
return (
<View style={styles.container}>
<Header/>
<ListView
style={styles.list}
automaticallyAdjustContentInsets={false}
dataSource={this.state.dataSource}
renderRow={(row) => this._renderMsgItem(row)}
/>
</View>
)
}
_renderMsgItem(msg) {
let user = api.getUserInfo(msg.from);
let ChatItem = ThemeService.getChatItemComponent();
msg.text = msg.text.length > 25 ? msg.text.substring(0,23)+'...' : msg.text;
return (
<ChatItem
user={user}
message={msg}
onClick={(user) => this._openChat(user)}
/>
);
}
_openChat(user) {
this.props.navigator.push({
screen: ThemeService.getChatScreen(true),
passProps: {
userId: user.id
}
});
}
}
const styles = StyleSheet.create({
container:{
flex: 1,
},
list: {
paddingTop: 10
},
});
I would like to substitute the data this screen renders, with my own code, like this:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
FlatList
} from 'react-native';
import ajax from '../util/ApiMock';
export class ChatListScreenBase extends Component {
constructor(props) {
super(props);
this.state = {
themeIndex: ThemeService.getCurrentThemeIndex()
}
}
state = {
data: []
}
async componentDidMount() {
const data = await ajax.getDataTest();
this.setState({data});
}
render() {
return (
<View style={styles.container} >
<Text style={styles.h2text}>
Black Order
</Text>
<FlatList
data={this.state.data}
showsVerticalScrollIndicator={false}
renderItem={({item}) =>
<View style={styles.flatview}>
<Text style={styles.name}>{item.title}</Text>
</View>
}
keyExtractor={item => item.title}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 50,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
h2text: {
marginTop: 10,
fontFamily: 'Helvetica',
fontSize: 36,
fontWeight: 'bold',
},
flatview: {
justifyContent: 'center',
paddingTop: 30,
borderRadius: 2,
},
name: {
fontFamily: 'Verdana',
fontSize: 18
},
email: {
color: 'red'
}
});
When I do this, I keep getting this error:
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of ChatListScreenBase."
I think that the problem is with the <FlatList>, but I'am not sure what type its expecting?
When I call the webservice it returns:
{"users":[{"_id":"5d0fcd8fe1dbfd7c23424e09","title":"180710","type":1,"published":"5"},{"_id":"5d0fcd8fe1dbfd7c23424e0a","title":"180705","type":3,"publiched":"5"},{"_id":"5d0fcd8fe1dbfd7c23424e0b","title":"Mr.
Nick","type":2,"publiched":"5"}]}
Kind regards.
For the looks of your API response you are setting data as object with key users and then trying to loop over it.
Instead update componentDidmount:
async componentDidMount() {
const resp = await ajax.getDataTest();
this.setState({ data: resp.users });
}

Flatlist data not showing up on screen

Trying to make a simple to-do list. My AddTodo component works fine and I don't believe it is causing the issue but my Flatlist does not show the data. I have no idea why as there are no errors. The issue appears with or without the scroll view.
I've tried messing around with the width and height of the items and the list itself but nothing seems to do the trick.
my mainTodo file:
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView } from 'react-native';
import AddTodo from './AddTodo';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo() {
let todos = this.state.todos;
todos.unshift({
id: todos.length + 1,
todo: this.state.textInput,
completed: false
});
this.setState({
todos,
textInput: ''
});
}
render() {
return (
<View style={{ flex: 1 }}>
<AddTodo
textChange={textInput => this.setState({ textInput })}
addNewTodo={() => this.addNewTodo()}
textInput={this.state.textInput}
/>
<ScrollView>
<FlatList
style={{ flex: 1 }}
data={this.state.todos}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</ScrollView>
</View>
);
}
}
export default MainTodo;
my TodoItem file:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
todoItem: {
width: 40,
height: 40,
borderBottomColor: '#DDD',
borderBottomWidth: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 15
}
});
export default TodoItem;
Under my addtodo component nothing shows up, it's just a blank screen.
In the maintodo file you are rendering the AddTodo component but i didn't see your AddTodo component. So you can update your code accordingly.
In the TodoItem remove the style applied to TouchableOpacity so that your code looks like
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
});
export default TodoItem;
And in the MainTodo
update your addNewTodo function as
addNewTodo = () => {
const todo = {
id: this.state.todos.length,
title: this.state.textInput,
completed: false
}
this.setState({todos: [...this.state.todos, todo ], textInput: ""})
}
create the TextInput and Button with parent View as flexDirection: "row" and so when TextInput is changed it's value is set in the textInput and when Button is pressed it will create new object and add it to the todos and set the value of TextInput to empty.
and final code can be as
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView, TextInput, Button } from 'react-native';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo = () => {
const todo = {
id: this.state.todos.length,
title: this.state.textInput,
completed: false
}
this.setState({todos: [...this.state.todos, todo ], textInput: ""})
}
render() {
return (
<View style={{ flex: 1, marginTop: 30, paddingHorizontal: 20 }}>
<View style={{flexDirection: "row", alignItems: "center", justifyContent: "space-between"}}>
<TextInput style={{borderWidth: 1, borderColor: "black"}} onChangeText={textInput => this.setState({textInput})} placeholder="Enter todo text" value={this.state.textInput} />
<Button onPress={this.addNewTodo} title="Add todo" />
</View>
<FlatList
contentContainerStyle={{flexGrow: 1}}
data={this.state.todos}
extraData={this.state.todos}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</View>
);
}
}
export default MainTodo;
use the code
mainTodo file:
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView } from 'react-native';
import AddTodo from './AddTodo';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo() {
let todos = this.state.todos;
todos.unshift({
id: todos.length + 1,
todo: this.state.textInput,
completed: false
});
this.setState({
todos,
textInput: ''
});
}
render() {
return (
<View style={{ flex: 1 }}>
<AddTodo
textChange={textInput => this.setState({ textInput })}
addNewTodo={() => this.addNewTodo()}
textInput={this.state.textInput}
/>
<ScrollView>
<FlatList
style={{ flex: 1 }}
data={this.state.todos}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</ScrollView>
</View>
);
}
}
export default MainTodo;
TodoItem file:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
todoItem: {
width: 40,
height: 40,
borderBottomColor: '#DDD',
borderBottomWidth: 1,
backgroundColor:'red',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 15
}
});
export default TodoItem;

React-native: how to store input value and data using AsyncStorage?

I have a form with a TextInput imported from react-native and DatePicker imported from native-base. I want to store their values on submit of the form using AsyncStorage.
I am getting an error: ReferenceError: ReferenceError:Input is not defined
This is component:
import React, { Component } from 'react';
import { View,StyleSheet, AsyncStorage, TextInput } from 'react-native';
import {
Form,
Button, Icon,
DatePicker, Text
} from 'native-base';
import PropTypes from 'prop-types';
class Reminder extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
chosenDate: new Date(),
};
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
this.setState({
chosenDate: newDate
});
}
handleChangeInput = (text) => {
this.setState({input:text});
}
//On application loads, this will get the already saved data and set the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("this.state.text").then((value) => {
this.setState({'this.state.text':value});
});
}
//save the input
saveData(value) {
console.log('value', value);
AsyncStorage.setItem("this.state", value);
this.setState({'this.state':value});
}
render() {
return (
<View>
<Form style={styles.formContainer}>
<View style={styles.formView}>
< TextInput
placeholder = "Set your reminder"
onChangeText={this.handleChangeInput}
value={input}
/>
<DatePicker
defaultDate={new Date()}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2019, 12, 31)}
locale={"en"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={false}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate}
/>
<Text style={styles.datePicker}>
{this.state.chosenDate.toString().substr(4, 12)}
</Text>
</View>
<View style={styles.footer}>
<Button block success style={styles.saveBtn}
onPress={ () =>
{this.saveData(value)
console.log('save data', value);}
}
>
<Icon type='MaterialIcons' name='done' />
</Button>
</View>
</Form>
</View>
);
}
}
const styles = StyleSheet.create({
formContainer: {
marginTop: 10,
padding: 10,
},
editIcon:{
color: '#28F1A6',
fontSize: 26,
},
editBtn:{
flex: 1,
alignSelf: 'flex-end',
},
datePicker:{
alignSelf: 'auto',
paddingLeft: 10
},
footer:{
position: 'relative',
top: 350
},
saveBtn: {
position:'relative',
marginTop: 35,
}
});
export default Reminder;
This is my screen:
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import PropTypes from 'prop-types';
import Reminder from '../components/Reminder';
const ReminderScreen = ({navigation}) => (
<View >
<Reminder navigation={navigation} >
<StatusBar backgroundColor = "#28F1A6" />
</Reminder >
</View>
);
Reminder.propTypes = {
navigation: PropTypes.object.isRequired
}
export default ReminderScreen;
I am fairly new to react-native. I am obviously doing missing out something, but not sure exactly what?
This is because in your TextInput component you set the props value to input instead of this.state.input
Or you can add this line before your return statement
const { input } = this.state;

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!

React Native `alignItems: 'flex-end'` hides content in TabBarIOS component

This question is similar to this one however I have different requirements. I have a <TabBarIOS> component that renders a <Camera> from react-native-camera. I need to place a button to take a picture at the bottom of the <Camera> component but above the <TabBarIOS> component.
index.ios.js
import React, { Component } from 'react';
import {
AppRegistry,
TabBarIOS,
ScrollView,
StyleSheet,
Text,
View
} from 'react-native';
import CameraTab from './views/CameraTab.ios.js';
import FilesTab from './views/FilesTab.ios.js';
import Icon from 'react-native-vector-icons/MaterialIcons';
export default class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'cameraTab'
};
};
_renderContent() {
switch (this.state.selectedTab) {
case "filesTab":
return <FilesTab style={styles.tabContent}></FilesTab>;
case "cameraTab":
return <CameraTab style={styles.tabContent}></CameraTab>;
case "settingsTab":
return <View style={styles.tabContent}></View>;
default:
return <View style={styles.tabContent}></View>;
}
};
render() {
return (
<TabBarIOS
tintColor="#3498db"
barTintColor="#ecf0f1">
<Icon.TabBarItemIOS
title="Files"
iconName="folder"
selected={this.state.selectedTab === "filesTab"}
onPress={() => {
this.setState({
selectedTab: "filesTab",
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS
title="Camera"
iconName="photo-camera"
badge={this.state.notifCount > 0 ? this.state.notifCount : undefined}
selected={this.state.selectedTab === "cameraTab"}
onPress={() => {
this.setState({
selectedTab: "cameraTab",
notifCount: this.state.notifCount + 1,
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS
title="Settings"
iconName="settings"
selected={this.state.selectedTab === 'settingsTab'}
onPress={() => {
this.setState({
selectedTab: "settingsTab",
presses: this.state.presses + 1
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
</TabBarIOS>
);
}
}
var styles = StyleSheet.create({
tabContent: {},
});
AppRegistry.registerComponent('myapp', () => myApp);
CameraTab.ios.js
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
View
} from 'react-native';
import Camera from 'react-native-camera';
export default class CameraTab extends Component {
constructor(props) {
super(props);
this.state = {};
};
render() {
return (
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
</Camera>
);
}
takePicture() {
this.camera.capture()
.then((data) => console.log(data))
.catch(err => console.error(err));
}
}
var styles = StyleSheet.create({
preview: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
height: Dimensions.get('window').height,
width: Dimensions.get('window').width
},
capture: {
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
height: 20
}
});
module.exports = CameraTab;
I've tried various things but the capture button is always hidden when alignItems: 'flex-end' is in the container component's style.
It should look something like this:
Edit: I've discovered this issue that describes a workaround (placing the button component outside of the camera component). According to RN's docs on Height and Width it seems that this solution will work for all screen dimensions. However this doesn't work for me because I want a Subview with icons inside the camera.
OK, finally fixed it. I think the problem had to do with the height and width in the preview style. Working code:
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableHighlight,
View
} from 'react-native';
import Camera from 'react-native-camera';
import Icon from 'react-native-vector-icons/Ionicons';
export default class CameraTab extends Component {
constructor(props) {
super(props);
this.state = {};
};
render() {
return (
<View style={styles.container}>
<Camera
ref={(cam) => {
this._camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}
captureTarget={Camera.constants.CaptureTarget.disk}>
<TouchableHighlight
style={styles.cameraButton}
onPress={this._takePicture.bind(this)}>
<Icon name="ios-qr-scanner" size={55} color="#95a5a6" />
</TouchableHighlight>
</Camera>
</View>
);
}
_takePicture() {
this._camera.capture()
.then((data) => {
console.log(data)
})
.catch((err) => {
console.error(err)
});
}
}
var styles = StyleSheet.create({
cameraButton: {
flex: 0,
flexDirection: 'row',
marginBottom: 60,
},
container: {
flex: 1,
},
preview: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'space-around'
},
});
module.exports = CameraTab;