Basically, I want to call function (class method) from inside the functionComponent in react-native. Only way i can do it by passing as a props as shown in example B (image with debugging info). I want to try it like in example A (image with debugging info); Is there some way to achieve that (not using props)? Or there is whole another way to do it, any suggestion or tips or tricks would be nice. Or am i missing something.
Code for Example A.
//Example A
import React from 'react';
import { Text, View, Button } from 'react-native';
export default class RegisterScreen extends React.Component{
state = { message: "state message"};
openDialog(){
alert("hello..");
}
funcComponent({text}){
console.log(this);
console.log(this.state.message);
return(
<View>
<Text>{text}</Text>
<Button onPress={()=> this.openDialog()} title="Open"/>
</View>
);
}
render(){
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<this.funcComponent text="hello from component." />
</View>
);
}
}
Example A Debugging Report Image
Code for Example B
//Example B
import React from 'react';
import { Text, View, Button } from 'react-native';
export default class RegisterScreen extends React.Component{
state = { message: "state message"};
openDialog(){
alert("hello..");
}
funcComponent({text, openDialog, context}){
console.log(context);
console.log(context.state.message);
return(
<View>
<Text>{text}</Text>
<Button onPress={()=> openDialog()} title="Open"/>
</View>
);
}
render(){
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<this.funcComponent text="hello from component." openDialog={this.openDialog} context={this} />
</View>
);
}
}
Example B Debugging Report Image
Edit:
Ok, basically the problem is with the component, we can't just use "this" operator inside the functioncomponent coz we are using in the <this.funcComponent> (in Example A) that is why we need to pass this operator as props (which is done in Example B). In Example A "this" operator is out of the scope so that is why we need to pass as props.
Hope this is helpful to other who is facing this problem.
Edit 2: Solution for what i looking for
I found new solution for using "this" operator inside method or function, to use this operator we need to make arrow function, which makes the function inside the scope of the class.
(Basically it's a ES6 pitfall) reference: #doppio react native Flatlist navigation
Code for Example C
//Example C
import React from 'react';
import { Text, View, Button } from 'react-native';
export default class RegisterScreen extends React.Component{
state = { message: "i m state message"};
openDialog(){
alert("hello..");
}
funcComponent=({text}) => {
console.log(this);
console.log(this.state.message);
return(
<View>
<Text>{text}</Text>
<Button onPress={()=> this.openDialog()} title="Open"/>
</View>
);
}
render(){
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<this.funcComponent text="hello from component." />
</View>
);
}
}
Related
I am making a simple app to practice using modals. I have my modal component in a separate file from App.js. I have a button inside the modal and outside of the modal that should toggle the visibility of the modal. To handle the visibility toggle, I have a method in App.js, setVisibility, that takes in a boolean arg and sets the isVisibility state. When I had the modal component defined within App.js earlier everything was working fine, but I'm not sure about accessing and setting the state of a component from another file.
My modal component:
import React, { Component } from "react";
import { View, Modal, TouchableHighlight, Text } from 'react-native';
export default class AppModal extends Component {
constructor(props) {
super(props);
this.state = {
isVisible: this.props.isVisible
}
this.toggleVisibility = this.toggleVisibility.bind(this);
}
toggleVisibility(show) {
this.props.setVisibility(show);
}
render() {
return (
<View>
<Modal
animationType='slide'
visible={this.state.isVisible}
onRequestClose={() => this.toggleVisibility(false)}
>
<View style={{alignItems: 'center', justifyContent: 'center', flex: 1}}>
<Text>Inside the modal</Text>
<TouchableHighlight style={{padding: 10}} onPress={() => this.toggleVisibility(false)} >
<Text>Press me</Text>
</TouchableHighlight>
</View>
</Modal>
</View>
)
}
}
My app.js:
import React, { Component } from 'react';
import { Text, View, TouchableHighlight } from 'react-native';
import AppModal from './AppModal'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
isVisible: false
}
this.setVisibility = this.setVisibility.bind(this);
}
setVisibility(show) {
this.setState({
isVisible: show
})
}
render() {
return (
<View style={{flex: 1}}>
<AppModal toggle={this.setVisibility} isVisible={this.state.isVisible} />
<View style={{justifyContent: 'center', alignItems: 'center', flex: 1}}>
<Text>Outside of the modal</Text>
<TouchableHighlight style={{padding: 10}} onPress={() => {this.setVisibility(true); console.log(this.state);}} >
<Text>Press me</Text>
</TouchableHighlight>
</View>
</View>
)
}
}
Now I get an error when I press the button in the modal which tells me that 'this.props.setVisibility is not a function'.
Please let me know if I can explain my question better. Thank you in advance!
You send the toggling callback method as toggle={this.setVisibility}, not setVisibility={this.setVisibility}, so your callback must be:
toggleVisibility(show) {
this.props.toggle(show);
}
I'm building a React Native app, it uses React Navigation. I use TouchableOpacity throughout the app, however, in a stack navigator screen, it doesn't seem to work at all. Touching the element doesn't change the opacity and the onpress function doesn't work. The screen itself displays fine and all other screens in my app have TouchableOpacity's that work fine.
Using button doesn't respond either, I'm thinking this is a react navigation issue potentially? There is no issues transitioning to the screen though?
Here is my screen;
import React, {Component} from 'react';
import { View, Text, TouchableOpacity, Alert, Button} from 'react-native';
class RaceScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<View style={{ flex: 1, alignItems: 'center', backgroundColor:'rgba(30,30,30,0.98)'}}>
<TouchableOpacity onPress = {() => console.log('Hello')}>
<View style={{ margin:50, height:100, width: 200, backgroundColor:'red', alignItems:'center', justifyContent:'center' }}>
<Text style={{ color:'white' }}>
Go back
</Text>
</View>
</TouchableOpacity>
<Button title="Go back button" onPress = {() => console.log('Hello')}>
</Button>
</View>
);
}
}
export default RaceScreen
I've found that the Touchable components typically don't respond well to text children. You simply need to wrap it inside a View:
import React, {Component} from 'react';
import { View, Text, TouchableOpacity, Alert} from 'react-native';
export default class RaceScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', backgroundColor:'rgba(30,30,30,0.98)'}}>
<TouchableOpacity onPress = {() => console.log('Hello')}>
<View style={{ margin:50, height:100, width: 200, backgroundColor:'red', alignItems:'center', justifyContent:'center' }}>
<Text style={{ color:'white' }}>
Go back
</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
I finally figured it out. In the createStackNavigator method from react-navigation, transparentCard:true is a deprecated property and was causing the bug. I was using version 3 documentation on a version 4 package of react navigation.
Looking at there site, they have just released version 5 which is great!
A note to the less experienced developers like myself, making sure you're aware of the version of each package you are using is critical for some of these difficult bugs. Don't let it get you down though, react native is elite!
I'm new at react native :D so..
I'm trying to build a simple page with inline style and when I use {{ like style={{}} return for me this error: Unexpected token and when I write like this style={} app run successfully but style not working
it's my code:
import React, { Component } from 'react';
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
Image,
StatusBar,
} from 'react-native';
import styles from "./outStyles";
class App extends Component {
render(){
return (
<View style={{flex=1}}>
<View style={{backgroundColor='#f00',flex=1}} ></View>
<View style={{backgroundColor='#00f',flex=9}} >
<Text>Usee First Project anbari</Text>
</View>
<View style={{backgroundColor='#00',flex=1}} ></View>
</View>
);
};
}
export default App;
The first set of curly braces in JSX indicates you are passing it a parameter. The second set in your example indicates that parameter is an object. But, your are not using valid JS object syntax. So instead of:
<View style={{backgroundColor='#f00',flex=1}} ></View>
Do this:
<View style={{ backgroundColor: '#f00', flex: 1 }} ></View>
It might be clearer for you if you separate your style object, like setting it up in your constructor:
this.styles = {
backgroundColor: '#f00',
flex: 1
};
Then in your render you could do:
<View style={this.styles} ></View>
When you pass the style to the <View>, tags are expecting style objects. So this is not going to work...
style={{ backgroundColor='#f00', flex=1 }}
It should be : not =, So this is how you should apply it...
style={{ backgroundColor:'#f00', flex:1 }}
I am trying to write a reusable Header Component in React-Native. I want to write it in a ways that the left and right button can be passed as child components. To know where to render which button I want to pass a prop like rightIcon or leftIcon. However I don't know how to access these props.
This is my App.js file
import React from 'react';
import {StyleSheet, TouchableHighlight, View} from 'react-native';
import Header from "./src/Header";
import {Ionicons} from '#expo/vector-icons';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Header headerText={"Barcode Scanner"}>
<TouchableHighlight righticon>
<Ionicons name="md-barcode" size={36} color="white"></Ionicons>
</TouchableHighlight>
</Header>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
});
And this is the Header Component
import React from 'react';
import {Text, View} from 'react-native';
export default class Header extends React.Component {
render() {
const {textStyle, viewStyle, rightButton} = styles;
return (
<View style={viewStyle}>
<Text style={textStyle}>{this.props.headerText}</Text>
<View style={rightButton}>
{this.renderRightChild()}
</View>
</View>
);
}
renderRightChild = () => {
console.log("Check if rightIcon Prop is set");
}
}
const styles = {
viewStyle: {
backgroundColor: '#5161b8',
justifyContent: 'center',
alignItems: 'center',
height: 80,
paddingTop: 25,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.2,
elevation: 2,
position: 'relative'
},
textStyle: {
color: '#fff',
fontSize: 20
},
rightButton: {
position: 'absolute',
top:
35,
right:
20
}
}
;
I already tried to use React.Children.toArray but this always throws an error that the request entity is too large.
Thanks for all the answers
I guess you can always use a render prop that way you can not only decide whether to render left/right icon component but the component rendering the icon does not even have to know what to render:
The term “render prop” refers to a simple technique for sharing code
between React components using a prop whose value is a function.
return (
<View style={styles.container}>
<Header
headerText={"Barcode Scanner"}
renderRightIcon={() => (
<TouchableHighlight righticon>
<Ionicons name="md-barcode" size={36} color="white" />
</TouchableHighlight>
)}
/>
</View>
);
Then you can use call the right icon as a function:
return (
<View style={viewStyle}>
<Text style={textStyle}>{this.props.headerText}</Text>
{renderLeftIcon && (
<View style={leftButton}>
{renderLeftIcon()}
</View>)
}
{renderRightIcon && (
<View style={rightButton}>
{renderRightIcon()}
</View>)
}
</View>
);
You render both components, the right and left and you put an if condition inside state.
Header Component render method
render() {
const { leftOrRight } = this.props // right - true, left - false
return(
...
{ leftOrRight ? <RightIcon /> : <LeftIcon />}
);
}
Inside Component that calls Header
import Header from './somepath ...';
class Something extends React.Component {
this.state = { leftOrRight }
render() {
return(
<Header leftOrRight = {this.state.LeftOrRight}/>
);
}
}
You could have a function that sets leftOrRight in your parent class
One way to do this is write a Header Component and pass all the things, as props, which you can then access them in Header Components Props like..
<Header title="HeaderTitle"
leftButtonTitle="LeftButton"
rightButton={canBeAObjectWithSomeInfo}
leftButtonClick={handleClick} />
and then in your header component(can be class or a function)
const Header = ({}) => (
<View>
<View onPress={this.props.handleClick}>{this.props.leftButton}</View>
<View>{this.props.title}</View>
<View onPress={this.props.handleRightClick}>{this.props.rightButton}</View>
</View>
)
something like this you can have and then you can design header accordingly
I'm having a problem with the Navigator in React Native. I want to navigate to another screen when pressing some Text, but I'm getting a strange error, I'm not too sure why.
Here's my code blocks and a picture of the error I'm receiving.
'use strict'
import React, { Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import ViewContainer from '../components/ViewContainer';
import StatusBarBackground from '../components/StatusBarBackground';
import AppNavigator from '../navigation/AppNavigator'
import UserIndexScreen from './UserIndexScreen'
class LoginIndexScreen extends Component {
render() {
return (
<ViewContainer>
<StatusBarBackground />
<View style={styles.textContainer}>
<Text style={styles.loginText}>Welcome to</Text>
<TouchableOpacity onPress={(event) => this._navigateToUserIndexScreen()}>
<Text style={styles.nextStep}>Press to go to User Index Screen</Text>
</TouchableOpacity>
</View>
</ViewContainer>
);
}
_navigateToUserIndexScreen() {
AppNavigator.props.push({
ident: "UserIndex"
})
}
}
const styles = StyleSheet.create({
textContainer: {
flex: 1,
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
loginText: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginTop: 30
},
nextStep: {
marginTop: 80
}
});
module.exports = LoginIndexScreen;
And here's the Navigator component.
'use strict'
import React, { Component } from 'react';
import { Navigator } from 'react-native';
import RegisterIndexScreen from '../screens/RegisterIndexScreen';
import LoginIndexScreen from '../screens/LoginIndexScreen';
import UserIndexScreen from '../screens/UserIndexScreen';
import PersonProfileScreen from '../screens/PersonProfileScreen';
class AppNavigator extends Component {
_renderScene(route, navigator) {
var globalNavigatorProps = { navigator }
switch(route.ident) {
case "RegisterIndexScreen":
return (
<RegisterIndexScreen {...globalNavigatorProps} />
)
case "LoginIndexScreen":
return (
<LoginIndexScreen {...globalNavigatorProps} />
)
case "UserIndex":
return (
<UserIndexScreen {...globalNavigatorProps} />
)
case "Temp":
return (
<Text>Hello</Text>
)
case "PersonProfileScreen":
return (
<PersonProfileScreen {...globalNavigatorProps}
person={route.person} />
)
default:
return (
<LoginIndexScreen {...globalNavigatorProps} />
)
}
}
render() {
return (
<Navigator
initialRoute={this.props.initialRoute}
ref="appNavigator"
renderScene={this._renderScene}
configureScene={(route) => ({...route.sceneConfig || Navigator.SceneConfigs.FloatFromRight, })} />
);
}
}
module.exports = AppNavigator;
Also here's a picture of the error I'm receiving:
Any ideas would be greatly appreciated!
Thanks!
You are trying to invoke a child component method in parent.
Method you are trying to invoke is not a part of your child component, you are calling RN Navigator method.
You should use navigator object that you passed to view in navigator renderScene function.
So in general you want to do sth. like:
In AppNavigator's _renderScene function pass navigator object:
<LoginIndexScreen nv={navigator} />
Then in LoginIndexScreen's _navigateToUserIndexScreen function use passed nv props:
this.props.nv.push({ ident: "UserIndex" })
You should also bind functions. Check https://facebook.github.io/react/docs/reusable-components.html#no-autobinding