I am trying to create a loading screen in React Native that will navigate to a confirmation screen once the time from a setTimeout function has been fulfilled. Currently, the screen loads, but does not navigate to the confirmation screen after the setTimeout interval.
import React from 'react';
import { Text, View, Image } from 'react-native';
import { Actions as NavigationActions } from 'react-native-router-
flux';
import styles from './styles';
export default class ProcessingLoader extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
setTimeout(this.navigateToConfirmation, 3000);
}
navigateToConfirmation() {
NavigationActions.checkoutConfirmation({ product: this.props.product, type: 'reset' });
}
renderLoader() {
return (
<View style={styles.textContainer}>
<Text style={styles.loaderText}>Processing Order ...</Text>
</View>
);
}
render() {
return (
<View style={{ flex: 1 }}>
{this.renderLoader()}
</View>
);
}
}
I've tried using setTimeout in componentDidMount as well as in render. I've also tried using and arrow function vs not using an arrow function. Am I utilizing setTimeout completely wrong here? I'm afraid that I don't understand why it will not navigate to the next screen after 3 seconds. Thanks in advance!
You are not invoking the function, use parenthesis to do that.
Also, the first parameter is a callback, so put your invokation inside a function, like this:
componentDidMount() {
setTimeout(function(t){t.navigateToConfirmation()}, 3000, this);
}
or in an arrow function:
componentDidMount() {
setTimeout(() => {this.navigateToConfirmation()}, 3000);
}
Related
I am a beginner in the react-native framework. I am building an sample mobile application. And I am stuck at the very basic step.
I am trying to call 'getBusinessNews()' function on click event, which will return a component. But due to some reason, it's not returning.
I have doubled checked the path of the component and its correct.
Even the console.log defined inside the function is getting displayed.
I am attaching the code, all kind of help is appreciated.
Thank you in advance.
import React, {Component} from 'react';
import {Text,View,TouchableOpacity} from 'react-native';
import BusinessNews from '../News/BusinessNews';
class categories extends Component{
render(){
return(
<View>
<TouchableOpacity onPress={this.getBusinessNews.bind(this)}>
<Text>Business News</Text>
</TouchableOpacity>
</View>
);
}
getBusinessNews(){
console.log(1);
return(
<BusinessNews />
);
}
export default categories;
Returning component from event handler/listener to render will not work.
Instead do state update to decide whether component BusinessNews will render or not.
Its should do like this.
constructor
constructor() {
this.state = {
showBusiness: false//initially set to false
}
}
getBusinessNews
getBusinessNews() {
this.setState({showBusiness: true})//set to true to show BusinessNews
}
render
render() {
render() {
return (
<View>
<TouchableOpacity
onPress={this
.getBusinessNews
.bind(this)}>
{this.state.showBusiness ===true && <BusinessNews/>}//check boolean true
<Text>Business News</Text>
</TouchableOpacity>
</View>
);
}
}
You can return a component on click. As you have to returns component in render() only. You need to change the logic to render component.
You can call <BusinessNews /> in somewhere in render() to add component.
I'm trying to wrap a button that already exists with the functionality of recordActivityTag. Right now the way it is working it is not capturing the function of the data from the first button. I need to follow tags throughout the app. That's why I've constructed recordActivityTag. That functionality works fine for events, except for buttons.
How do I call within the onPress - if that's possible - the action on a button from another screen? I know I need to pass in the outer prop into TouchableOpacity and then call the other button.
import * as React from "react";
import { Core } from "common";
import { TouchableOpacity } from "react-native";
interface BtnProps {
readonly data: string
readonly recordActivityTag:(tag: Core.ActivityTag) => void
}
export default class Button extends React.Component<BtnProps, {}> {
constructor(props: BtnProps) {
super(props);
}
render() {
const { recordActivityTag } = this.props;
return (
<TouchableOpacity>
onPress {() => recordActivityTag}
{this.props.children}
</TouchableOpacity>
);
}
}
Make sure that you give your function to the onPress prop of the TouchableOpacity component, and that you actually call recordActivityTag within it.
export default class Button extends React.Component<BtnProps, {}> {
render() {
const { recordActivityTag } = this.props;
return (
<TouchableOpacity onPress={() => recordActivityTag()}>
{this.props.children}
</TouchableOpacity>
);
}
}
I have a screen inside my react-navigation StackNavigator that looks like this:
import React from 'react';
import { FlatList, ScrollView, StyleSheet, Text, View } from 'react-native';
import { List, ListItem } from 'react-native-elements';
import Accordion from '#ercpereda/react-native-accordion';
export default class PassportScreen extends React.Component {
static navigationOptions = {
title: 'Passport Recovery',
};
constructor(props) {
super(props);
this.renderItem = this.renderItem.bind(this);
}
renderItem(item) {
return (
<View>
<Accordion
header={item.item.key}
content={item.item.content}
/>
</View>
)
}
render() {
const instructions = [
{
key: <Text>1. Fill out a passport application form</Text>,
content: <Text>Content</Text>
},
{
key: <Text>2. Fill out a lost/missing passport statement</Text>,
content: <Text>Content</Text>
},
///...etc
];
return (
<ScrollView>
<FlatList
data={instructions}
renderItem={this.renderItem}
/>
</ScrollView>
)
}
}
module.exports = PassportScreen;
however, when I click to navigate to this screen from another screen, I get this error: TypeError: this.props.header is not a function. (In 'this.props.header({
isOpen: this.state.is_visible
})', 'this.props.header' is an instance of Object).
Other questions I've looked at with similar errors have mentioned passing props to the constructor and needing to pass this.renderItem instead of this.renderItem(), both of which I have already done, so I'm wondering if the problem comes from the fact that this screen is inside a StackNavigator and is navigated to by clicking on a ListItem. Is my intuition correct? If so, how can I fix this?
It seems that the header prop accepts a function, rather than just a component like content does.
Right now you're directly passing an object to the header prop, therefore it won't accept the callback function.
You may try the following approach in order to pass a callback to the header.
PassportScreen.js
customFunc = (callback) => {
console.log(callback)
}
renderItem = (item) => { // Useful to bind `this`
return (
<View>
<Accordion
header={this.customFunc}
content={item.item.content}
/>
</View>
)
}
ChildComponent.js
this.props.header('I'm setting the callback here')
I've been trying to call a function which is in a screen of a navigator from its screen.
To clarify the point, here is a snippet of my code...
//ScreenA.js
export default class ScreenA extends React.Component {
showWarning(){
this.setState({showWarning: true});
setTimeout(function() {
this.setState({showWarning: false});
}.bind(this), 3000);
}
render() {
return (
<View style={{backgroundColor : this.state.showWarning ? "#red" : "#blue"}}>
{this.state.showWarning && <Warning />}
</View>
)
}
}
//Nagigator.js
default export const Navigator = StackNavigator({
ScreenA: {screen: ScreenA},
ScreenB: {screen: ScreenB},
});
//App.js
export default class App extends React.Component {
handleSubmit(qrCode){
if(qrCodeIsInvalid){
this.navigator.ScreenA.showWarning();
//This is just a sudo code.
//How do we call ScreenA.showWarning here?
}
}
render() {
let props = {/*some props here*/};
return (//This "ref" stops the application without describing any reason
<Navigator screenProps={props} ref={nav => { this.navigator = nav; }}/>
);
}
}
There is an example of how to call a function from a navigation header, but not from the class which exports the navigator.
I thought that each screen can be accessed via ref, but this causes an error without explaining what's happening.
Has anyone encountered a similar situation?
Any advice will be appreciated.
P.S.
# Nimrod Argov
Here are details of what I've been trying to achieve.
ScreenA has a QR code reader and submit function, which submits QR codes to App.js.
App.js has handleSubmit function, where submitted QR codes are sent to a server and labelled as either valid or invalid.
If a submitted QR code turns out to be invalid, ScreenA has to show a warning message and change its background colour for 3 seconds.
It might be achieved by having App.js pass a prop {showWarning:true} to ScreenA and pass {showWarning:false} in 3 seconds.
However, I thought it would be ScreenA's responsibility to change its background colour. Thus, I set setTimeout and setState in the showWarning().
I did it this way:
ScreenA.js
While navigate to ScreenB, including the function you want to call.
export default class ScreenA extends React.Component {
constructor(props) {
super(props);
this.doSomething = this.doSomething.bind(this);
}
doSomething() {
this.setState({blah: true});
}
navigateToB() {
this.props.navigation.navigate('ScreenB', {
doSomething: this.doSomething,
});
}
}
ScreenB.js
So you can do this in ScreenB.
const { state, setParams, navigate } = this.props.navigation;
const params = state.params || {};
params.doSomething();
So i have a Drawer.Js using 'react-native-off-canvas-menu' where the sole purpose is to open and close the drawer. The problem is that this drawer will only open and close with gesture (slide left/right). I want to bind this open and close function with a button. The problem is it shows an error when i try to call function handleClick from Home.Js to my Drawer.Js
Inside my Drawer.Js
class FirstScreen extends Component {
constructor(props) {
super(props);
this.state = {
menuOpen: false
};
this.handleClick = this.handleMenu.bind(this);
}
handleMenu() {
const { menuOpen } = this.state;
this.setState({
menuOpen: !menuOpen
});
}
// Some Render Method Where i tried to create a button, and calling
this.handleMenu() on the onPress event, and it's successful
*//After the Render Method
export function a() {
return this.handleClick();
}
I am also using react native router flux which the first route of my apps is going to Home.js, where in Home.js i am going to put a button to trigger the drawer to open.
Here's my code for Home.js
*//Some Import
import { a } from './Drawer';
class Home extends Component {
constructor(props) {
super(props);
this.handleKlik = this.handleKlik.bind(this);
}
handleKlik() {
a();
}
*// Render Method Start
<View>
<TouchableOpacity onPress={() => this.handleKlik()}>
<View style={styles.btnContainer}>
<Text style={styles.btnText}>{'Toggle'.toUpperCase()}
</Text>
</View>
</TouchableOpacity>
<View>
Well here in Home.js, when i tried to click the button, i received and error like 'undefined is not a function (evaluting 'this.handleClick')'.
Well i think i know the problem where my export function is probably the problem. Can anyone please elaborate on how can i fix this? i've read the tutorial and i can't seem to understand why it's so hard to call a function inside another Js Files in my project