I'm using React native navigation. (Stack Navigation).
But I can't call function in navigationOptions. Not working.
import React, { Component } from 'react';
import { StyleSheet, View, Text, TouchableHighlight, AsyncStorage, Alert } from 'react-native';
import { Button } from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import HandleBack from '../../HandleBack';
export default class Dashboard extends Component {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => {
return {
title: 'Dasboard',
headerLeft: null,
headerRight: (
<TouchableHighlight underlayColor='transparent' onPress={this.login.bind(this)} style={{marginRight: 10}}>
<Icon
name="power-off"
size={25}
color="white"
/>
</TouchableHighlight>
)
};
};
login() {
alert('Button clicked!');
}
onBack = () => {
this.props.navigation.navigate('Screen3');
};
render() {
return(
<HandleBack onBack={ this.onBack }>
<View>
<Text> This is screen 2 </Text>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Screen3')}>
<Text> Go to Screen 3 </Text>
</TouchableHighlight>
</View>
</HandleBack>
)
}
}
When I'm using onPress={this.login.bind(this)} get error
"TypeError: TypeError: undefined is not an object (evaluatinh '_class.login.bind')"
When I'm using onPress={this.login} no reaction.
When I'm using onPress={this.login()} get error
TypeError: TypeError: _class.login is not a function.
But
I'm using onPress={() => alert('test')} is working.
you can achieve it using setParams or getParams for react-navigation.
export default class Dashboard extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: 'Dasboard',
headerLeft: null,
headerRight: (
<TouchableHighlight underlayColor='transparent'
onPress={navigation.getParam('login')} //call that function in onPress using getParam which we already set in componentDidMount
style={{marginRight: 10}}>
<Icon
name="power-off"
size={25}
color="white"
/>
</TouchableHighlight>
)
};
};
login() {
alert('login click')
}
onBack = () => {
this.props.navigation.navigate('Screen3');
};
componentDidMount() {
this.props.navigation.setParams({ login: this.login }); //initialize your function
}
render() {
return(
.....
)
}
}
Related
when i run it in expo it says "can't find variable navigation" , I can't seem to figure out why navigation isn't working does anyone have any ideas? I've tried taking this.props away etc but that doesn't work either
'use strict'
import React, { Component } from 'react';
import {
Text,
TextInput,
TouchableHighlight,
StatusBar,
ListView,
FlatList,
View
} from 'react-native';
import firebaseApp from './firebaseConfig.js';
import styles from './styles.js';
class Rooms extends Component {
static navigationOptions = {
title: 'Rooms',
header: null
};
constructor(props) {
super(props);
var firebaseDB = firebaseApp.database();
this.roomsRef = firebaseDB.ref('rooms');
this.state = {
rooms: [],
newRoom: ''
}
}
componentDidMount() {
this.listenForRooms(this.roomsRef);
}
listenForRooms(roomsRef) {
roomsRef.on('value', (dataSnapshot) => {
var roomsFB = [];
dataSnapshot.forEach((child) => {
roomsFB.push({
name: child.val().name,
key: child.key
});
});
this.setState({ rooms: roomsFB });
});
}
addRoom() {
if (this.state.newRoom === '') {
return;
}
this.roomsRef.push({ name: this.state.newRoom });
this.setState({ newRoom: '' });
}
openMessages(room) {
this.props.navigation.navigate('Messages', {roomKey: room.key, roomName: room.name});
}
renderRow(item) {
return (
<TouchableHighlight style={styles.roomLi}
underlayColor="#fff"
onPress={() => this.openMessages(item)}
>
<Text style={styles.roomLiText}>{item.name}</Text>
</TouchableHighlight>
)
}
render() {
return (
<View style={styles.roomsContainer}>
<StatusBar barStyle="light-content"/>
<Text style={styles.roomsHeader}>Chatypus</Text>
<View style={styles.roomsInputContainer}>
<TextInput
style={styles.roomsInput}
placeholder={"New Room Name"}
onChangeText={(text) => this.setState({newRoom: text})}
value={this.state.newRoom}
/>
<TouchableHighlight style={styles.roomsNewButton}
underlayColor="#fff"
onPress={() => this.addRoom()}
>
<Text style={styles.roomsNewButtonText}>Create</Text>
</TouchableHighlight>
</View>
<View style={styles.roomsListContainer}>
<FlatList
data={this.state.rooms}
renderItem={({item}) => (this.renderRow(item)
)}
/>
</View>
</View>
);
}
}
export default Rooms;
I want to make a component where it renders a modal.
This component should have states{Key(integer),ImageLink(string),Visible(bool)}.
I am using flatlist. I want to render the component's modal on flatlist parent but component. States changes upon touch on flatlist child.
For example:
Modal Component which means to be single instance
import React from "react";
import {
View,
Modal,
Text,
StyleSheet,
TouchableHighlight,
Platform
} from "react-native";
export default class MySingleInstanceModal extend Component{
constructor(props) {
super(props);
this.state = {
Visiable: props.Visiable, \\Bool For turning Modal On or Off
ImageLink: props.ImageLink, \\String Image Online Link
Key: props.PostKey,\\integer Key
};
}
NextImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current+1 });
};
ToggleMeOff = () => {
this.setState({ TurnMeOn: false });
};
ToggleMeOn = (MyKey,MyLink) => {
this.setState({ TurnMeOn: true,ImageLink: MyLink,Key:MyKey });
};
PrevImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current-1 });
};
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.state.TurnMeOn}
>
<View style={{ marginTop: 22 }}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={this.ToggleMeOff}>
<Text>Hide Modal</Text>
</TouchableHighlight>
<Image
source={{ uri: this.state.ImageLink }}
resizeMethod={"resize"}/>
</View>
</View>
</Modal>
</View>
);
}
}
Calling In Flatlist Parent:
render() {
return (
<View style={Style1.container}>
<MySingleInstanceModal/> // Here I want to call render
<FlatList
data={data}
initialNumToRender={4}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
onEndReached={this._reachedEnd}
refreshing={isRefreshing}
onEndReachedThreshold={0.5}
onRefresh={this._refreshdata}
ListFooterComponent={this.renderFooter}
/>
</view>)
}
And want to change states of MySingleInstanceModal in flatlist items(flatlist child)
somewhere in the rendering of flatlist child item
render(){
return (
...
<TouchableHighlight onPress={() =>
MySingleInstanceModal.ToggleMeOn(this.state.Link,this.state.Key)}>
<Text>Open Modal For Me</Text>
</TouchableHighlight>
...
)
}
Which means component will render at parent but its states will be controlled by the child(Every flatlist item)
I have followed many guides on interner but I have never managed to make it work. This class opens the qrcode scanner and should insert the string inside the 'qrcode' variable, but I just can not.
This is my class:
import React from 'react';
import { StyleSheet, Text, View, TextInput, AppRegistry, TouchableOpacity } from 'react-native';
import { Constants, BarCodeScanner, Permissions } from 'expo';
class HomeScreen extends React.Component {
render() {
return (
<Text style={styles.input}>
1) QRCode:
<Text style={styles.inputPos}> {qrcode} </Text>
</Text>
<TouchableOpacity
style={styles.button}
onPress={() => {
this.props.navigation.navigate('Details')}
}>
<Text> SCAN </Text>
</TouchableOpacity>
</View>
);
}
}
class ScanQRCode extends React.Component {
state = {
hasCameraPermission: null
};
componentDidMount() {
this._requestCameraPermission();
}
_requestCameraPermission = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
this.setState({
hasCameraPermission: status === 'granted',
});
};
_handleBarCodeRead = data => {
Alert.alert(
'Scan successful!',
JSON.stringify(data)
);
qrcode = data;
};
render() {
return (
<View style={styles.container2}>
{this.state.hasCameraPermission === null ?
<Text>Requesting for camera permission</Text> :
this.state.hasCameraPermission === false ?
<Text>Camera permission is not granted</Text> :
<BarCodeScanner
onBarCodeRead={this._handleBarCodeRead}
style={{ height: 200, width: 200 }}
/>
}
</View>
);
}
}
I want the variable 'data' scanned by the qrcode to enter the variable 'qrcode' and display it next to it
I have the following problem.
I am creating a React Native appliation and I want to pass a click handler to a child component. But when I try to call the click handler in the child component I keep getting a _this.props.onItemPress is not a function Exception.
When I try to pass the function with a .bind(this) inside the parent, it says the function is undefined.
Here's my code:
Parent
constructor(props) {
super(props)
this.handleTodoPress = this.handleTodoPress.bind(this)
}
...
handleTodoPress(event) {
console.warn('Press handled')
}
renderItem ({section, item}) {
return <TodoItem onItemPress={this.handleTodoPress} title={item.title} description={item.description} completed={item.completed} />
}
...
render () {
return (
<View style={styles.container}>
<SectionList
renderSectionHeader={this.renderSectionHeader}
sections={this.state.data}
contentContainerStyle={styles.listContent}
data={this.state.dataObjects}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
initialNumToRender={this.oneScreensWorth}
ListHeaderComponent={this.renderHeader}
SectionSeparatorComponent={this.renderSectionSeparator}
ListEmptyComponent={this.renderEmpty}
ItemSeparatorComponent={this.renderSeparator}
renderSectionFooter={this.renderSectionFooter}
/>
</View>
)
}
}
Child
import React, { Component } from 'react';
import { TouchableOpacity, View, Text, } from 'react-native';
import styles from './Styles/TodoItemStyles'
export default class TodoItem extends Component {
constructor(props) {
super(props)
this.state = {completed: 'Todo'}
this.setCompletedState = this.setCompletedState.bind(this)
}
itemPressed = (e) => {
console.warn(this.props);
this.props.onItemPress(e)
}
setCompletedState() {
if (this.props.completed == true) {
this.setState({completed: 'Completed'})
}
}
componentWillMount() {
this.setCompletedState()
}
render() {
return (
<TouchableOpacity onPress={this.itemPressed}>
<View style={styles.todoContainer}>
<Text style={styles.itemTitle}>{this.props.title}</Text>
<Text style={styles.itemDescription}>{this.props.description}</Text>
<Text style={[styles.itemLabel, this.props.completed ? styles.itemLabelCompleted : styles.itemLabelNotCompleted]}>{this.state.completed}</Text>
</View>
</TouchableOpacity>
);
}
}
TRY:
export default class TodoItem extends Component {
constructor(props) {
super(props)
this.state = {completed: 'Todo'}
this.setCompletedState = this.setCompletedState.bind(this)
}
itemPressed(e){
console.warn(this.props);
this.props.onItemPress(e)
}
setCompletedState() {
if (this.props.completed == true) {
this.setState({completed: 'Completed'})
}
}
componentWillMount() {
this.setCompletedState()
}
render() {
return (
<TouchableOpacity onPress={this.itemPressed}>
<View style={styles.todoContainer}>
<Text style={styles.itemTitle}>{this.props.title}</Text>
<Text style={styles.itemDescription}>{this.props.description}</Text>
<Text style={[styles.itemLabel, this.props.completed ? styles.itemLabelCompleted : styles.itemLabelNotCompleted]}>{this.state.completed}</Text>
</View>
</TouchableOpacity>
);
}
}
when you use
itemPressed = (e) => {
console.warn(this.props);
this.props.onItemPress(e)
}
that notations binds the current context inside the function
I think your problem is that how you are using arrow function for itemPressed. Try rewriting it and binding this for itemPressed the same as you did for setCompletedState.
iam new in react native and start my first project , i have a login screen and when i press into TouchableHighlight i need to open another screen , but the problem is i failed to make the function that move from login to second screen , this is my code
Login.js
import React, { Component } from 'react';
import { AppRegistry, Text,SecureView ,Button,Image,TextInput,StyleSheet,View,NavigatorIOS,TouchableHighlight} from 'react-native';
require('./HygexListView.js');
class LoginView extends Component {
constructor(props){
super(props);
}
onPositive(){
this.props.navigator.pop()
};
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>
HYGEX
</Text>
<View>
<TextInput
placeholder="Username"
style={styles.formInput}
/>
<TextInput
placeholder="Password"
secureTextEntry={true}
style={styles.formInput1}
/>
<TouchableHighlight style={styles.button}
onPress={ () => this.onPositive() }>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
</View>
);
}
onPress() {
this.props.navigator.push({
title: "HygexListView",
component: HygexListView,
});
}
}
and when press into TouchableHighlight i need to open this screen
HygexListView.js
'use strict';
import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View } from 'react-native';
class HygexListView extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
}
render() {
return (
<View style={{flex: 1, paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
}
module.exports = HygexListView;
From what i see there, i think you forgot to use/setup the Navigator component. Try to organize it this way:
Your components
class HygexListView extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
}
render() {
return (
<Navigator
renderScene={this.renderScene.bind(this)}
navigator={this.props.navigator}
navigationBar={
<Navigator.NavigationBar style={{backgroundColor: 'red', alignItems: 'center'}}
routeMapper={NavigationBarRouteMapper} />
} />
);
}
renderScene(route, navigator) {
return (
<View style={{flex: 1, paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
}
module.exports = HygexListView;
index.ios.js
class yourApp extends Component {
render() {
return (
<Navigator
initialRoute={{id: 'Login'}}
renderScene={this.renderScene.bind(this)}
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.PushFromRight;
}} />
);
}
renderScene(route, navigator) {
switch (route.id) {
case 'HygexListView':
return (
<HygexListView navigator={navigator} />
);
case 'Login':
return (
<Login navigator={navigator} />
);
default:
return null;
}
}
}
basically what you do, instead of rendering your component, you render your navigator that using renderScene() renders your component/view.
the approach to use the index file as an organizer of the views, is just a preference of mine. but you will see there, that when an "id" is passed to the navigator, the scene will be rendered using the component that matches the id on the switch case.