// I am using below code for navigating one screen to another i.e Home page .
But when am navigating home page , I have to refresh the page ..reload . In current , when i am coming to home screen non of the life cycle method is getting call . Specially UserAvatar component I have to refresh ,or recall .
Please suggest
<View style={{textTransform: 'lowercase'}}><YellowBtn label="Go to
Dashboard"
OnClick={this._redirectCustomerView}/></View>
_redirectCustomerView = () => {
this.props.navigation.navigate('UserHome');
};
// Below is home page
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { title: 'Hello!', hasFooterPermission: false };
console.log("Valuueeeeeee");
}
async componentDidMount() {
const homeFooter = await hasPermission('clm.360D.fe.restrictedView.allowed');
this.setState({
hasFooterPermission: homeFooter
})
}
onSearchClick = () => {
this.props.navigation.navigate('SubscriberSearch');
};
componentWillMount(){
console.log(" Home page dataaaa");
}
render() {
return (
<View>
<ImageBackground source={BG} style={{ width: '100%', height: '100%' }} resizeMode="cover">
<View style={{ paddingTop: 5 , alignContent:'space-between',flexDirection:'row'}}>
<View style={{alignSelf: 'flex-start', flex:1}}>
<UserAvatar navigationProps={this.props.navigation} avatarSize={40} isTouchable={true}/>
</View>
{/* <View style={{alignSelf: 'flex-end'}}>
<Icon
name="bell-outline"
type="MaterialCommunityIcons"
style={{ color: '#FFFFFF' }}
onPress={() => Toastr.showToast('No new notifications!', 3000)}
/>
</View> */}
</View>
use push instead of navigate
this.props.navigation.push('UserHome');
It is not homepage duty to know if you have to refresh the page. The suggested approach is that when the condition to reload is met (avatar update, user properties changes, etc) then the calling entity should go to the homepage and if needed ask for a reload (i.e., window.location.reload(true))
If you add a listener on the home page through the navigation prop, you can call a function when a transition to or from the home page is about to happen ('willFocus'/'willBlur') or if it has completed ('didFocus'/'didBlur').
This worked for me:
componentDidMount(){
this.props.navigation.addListener('willFocus',this.load)
}
load = () => {
//whatever you want to do when the page loads
}
Documentation here: https://reactnavigation.org/docs/en/navigation-prop.html
Related
This question is an extension of this question and it is from the same member who asked this.
First, his problem was, how to authenticate before navigating to screens. But then, he asked, how to adapt that navigated new screen to the particular tab in the bottom tab navigator (Let's say Tab1). That means, after it is navigated to a particular screen after authenticated, he wants to click on another tab (Let's say Tab2), and then click on the previous tab (Tab1) and the navigated screen should still display on that previous tab (Tab1).
I've provided my answer to this new question below...
This is the solution that I'm suggesting.
This answer is an extension of the answer in the first question.
Home.js
import React, { Component } from 'react';
import { Text, View, TouchableOpacity, ScrollView } from 'react-native';
import PasswordInputModal from './PasswordInputModal'
import HelderScreen from 'path/to/HelderScreen';
import LolsScreen from 'path/to/LolsScreen';
import AthleanScreen from 'path/to/AthleanScreen';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
screen: null,
}
}
switchScreen = () => {
switch (this.state.screen) {
case 'Helder' : return <HelderScreen />;
case 'Lols' : return <LolsScreen />;
case 'Athlean': return <AthleanScreen />;
default : this.setState({ screen: null });
}
}
render() {
if(this.state.screen) { return this.switchScreen() }
return (
<View style={styles.container}>
<ScrollView style={styles.flatlist}>
<View style={styles.flatlist1}>
<TouchableOpacity onPress={() => this.PasswordInputModal.open('Helder')}>
<Text style={styles.item}>Empresa do Helder</Text>
</TouchableOpacity>
</View>
<View style={styles.flatlist1}>
<TouchableOpacity onPress={() => this.PasswordInputModal.open('Lols')}>
<Text style={styles.item}>Lols Inc</Text>
</TouchableOpacity>
</View>
<View style={styles.flatlist1}>
<TouchableOpacity onPress={() => this.PasswordInputModal.open('Athlean')}>
<Text style={styles.item}>Tesla Portugal</Text>
</TouchableOpacity>
</View>
</ScrollView>
<PasswordInputModal
ref={modal => this.PasswordInputModal = modal}
navigation={this.props.navigation}
onAuthentication={(screen) => this.setState({ screen })} />
</View>
);
}
}
Here, if the state called screen is set to the particular name of the screen, it will conditionally render that particular screen. Otherwise, it will render the buttons to go to those screens.
PasswordInputModal.js
import React, { Component } from 'react';
import { View, TextInput, Button } from 'react-native';
import Modal from 'react-native-modal';
export default class PasswordInputModal extends Component {
constructor(props) {
super(props);
this.state = {
password : '',
isVisible : false,
screen : null,
};
}
open = (screen) => this.setState({ isVisible: true, screen: screen });
close = () => this.setState({ isVisible: false });
onPressSubmitButton = () => {
//Use any authentication method you want according to your requirement.
//Here, it is taken as authenticated if and only if the input password is "12345".
const isAuthenticated = ("12345" == this.state.password); //If input password is '12345', isAuthenticated gets true boolean value and false otherwise.
if(isAuthenticated) {
this.props.onAuthentication(this.state.screen);
}
else {
console.log("Invalid password"); //Prompt an error alert or whatever you prefer.
}
this.close();
}
renderModalContent = () => (
<View>
<TextInput type={'password'} value={this.state.password} onChangeText={(password) => this.setState({ password })} />
<Button onPress={() => this.onPressSubmitButton()} title="Submit" color="#841584" />
</View>
);
render() {
return (
<Modal
isVisible={this.state.isVisible}
backdropColor="#000000"
backdropOpacity={0.9}
animationIn="zoomInDown"
animationOut="zoomOutUp"
animationInTiming={600}
animationOutTiming={600}
backdropTransitionInTiming={600}
backdropTransitionOutTiming={600}
>
{this.renderModalContent()}
</Modal>
);
}
}
What I've done here is, when the user is authenticated, a state called screen is set to the name of the screen which should be displayed. Actually, this is not something like navigating. This is actually called Conditional Rendering.
I didn't test this code myself. I hope this will help to the member who asked this question.
I have a question. I have a loader and during the loading I would show three different texts. Like text1, then this disappear and it's show text2 and then text3.
<View style={style.container}>
<View style={style.page}>
<ActivityIndicator size="large" color="#56cbbe" />
<Text>Text1.. </Text>
<Text>Text2.. </Text>
<Text>Text3.. </Text>
</View>
</View>
In this case I only show the three texts together. How can I do?
Thank you :)
One way to solve this is to use setInterval and call update function to loop through the texts assuming if they are present in form of array.
Simply saying for example.
Let's maintain loadingText in state as loadingText: ['text1', 'text2', 'text3'],A variable to track the present item as currentLoadingTextIndex: 0 and call setInterval in componentDidUpdate.
Be careful when calling update function in here,as one wrong mistake will make your app crash.
componentDidUpdate(prevProps, prevState) {
if (!prevState.isLoading && this.state.isLoading) {
this.timerId = setInterval(this.changeLoadText, 2000);
} else if (prevState.isLoading && !this.state.isLoading) {
clearInterval(this.timerId);
}
}
and finally our update function
changeLoadText = () => {
this.setState(prevState => {
return {
currentLoadingTextIndex:
(prevState.currentLoadingTextIndex + 1) %
prevState.loadingText.length,
};
});
};
I am attaching a working expo Demo for clarity purpose.
What you want is to show indicator and text1 during loading time and then text2 and text3. Is that right?
So I made an example for you. This should solve the problem by changing the status value. You can display the indicator for the duration of loading and show the text by changing the status value when loading is complete.
Example Code
//This is an example code to understand ActivityIndicator//
import React from 'react';
//import react in our code.
import { ActivityIndicator, Button, View, StyleSheet,Text } from 'react-native';
//import all the components we are going to use.
export default class App extends React.Component {
state = { showIndicator: true };
componentDidMount() {
setTimeout(() => {this.setState({showIndicator: false})}, 2000)
}
onButtonPress = () => {
//function to change the state to true to view activity indicator
//changing state will re-render the view and indicator will appear
};
render() {
//Check if showIndicator state is true the show indicator if not show button
if (this.state.showIndicator) {
return (
<View style={styles.container}>
{/*Code to show Activity Indicator*/}
<ActivityIndicator size="large" color="#0000ff" />
<Text>Text1.. </Text>
{/*Size can be large/ small*/}
</View>
);
} else {
return (
<View style={styles.container}>
<Text>Text2.. </Text>
<Text>Text3.. </Text>
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
alignItems: "center"
},
});
I currently have a static navigationOptions on every single page where I override the backbutton. I'm trying to change this so it uses defaultNavigationOptions instead. How do I access the back functionality of the navigationstack from the navigation file itself?
Current code:
const LoginNavigator = createStackNavigator(
{
// screens
},
{
headerLeft: (
<TouchableHighlight
onPress={() => /* navigate back */}
style={{ alignSelf: "center", marginLeft: 10 }}
>
<FontAwesomeIcon icon={faArrowLeft} color="#ffffff" />
</TouchableHighlight>
)
}
}
);
export const LoginNavigation = createAppContainer(LoginNavigator);
This gets imported into the main app, may that help.
In my app, I have defined a default class A in module xyz.js that renders a page on my navigation stack. Depending on one of class A's state variables, the views that are rendered differ. For example, if the app is placed in an "edit mode", then an editing view is rendered in addition to the other standard views rendered when the app is not in the "edit mode". I can't figure out how to change that state variable from a different module abc.js and cause the views associated with the instantiated class A to re-render. In my module abc.js, I create the navigation stack and I have an onPress handler for a touchableHighlight button to place the app in "edit mode". In that handler, I attempt to call a function "Edit()" in class A. But the function does not seem to get invoked. It may have something to do with binding, but that concept is not something I fully understand.
Here is what I have:
Module abc.js:
import XYZ from './xyz';
import {Edit} from './xyz';
import { pencilEditButton } from './Images';
const App = createStackNavigator(
{
Home: {
screen: My App,
navigationOptions: ({ navigation }) => ({
title: 'myApp',
headerRight: (
<View>
<TouchableHighlight
onPress={() => Edit()}
underlayColor="gray">
<View>
<Image source={pencilEditButton} style={styles.navigationButtonImage} />
</View>
</TouchableHighlight>
</View>
),
}),
},
}
);
export default createAppContainer(App);
Module xyz.js:
export default class XYZ extends React.Component {
constructor(props) {
super(props);
this.state = {
editMode: false,
};
};
// Create a method to handle the press of the edit button on the navigation bar
Edit() {
console.log("editMode: ", editMode);
this.setstate({ editMode: true });
console.log("editMode: ", editMode);
alert('User wants to edit a mix!');
};
render() {
return (
<View style={styles.container}>
{ this.state.editMode === true ?
<TouchableHighlight
onPress={this._onXPressed}
underlayColor="white">
<View style={[styles.flowRight, styles.controlButton]}>
<Text style={styles.buttonText}>{'Edit Mode'}</Text>
</View>
</TouchableHighlight>
:
<TouchableHighlight
onPress={this._onYPressed}
underlayColor="white">
<View style={[styles.flowRight, styles.controlButton]}>
<Text style={styles.buttonText}>{'Non Edit Mode'}</Text>
</View>
</TouchableHighlight>
}
</View>
);
}
}
So as you can see, there is a function called "Edit()" after the constructor in class XYZ of module xyz.js. This function is called from module abc.js when the edit button is pressed. But when the edit button is pressed, the state is not updated, the alert view is not displayed, and the views are not re-rendered. How do I correctly call Edit() so that the state variable "editMode" is updated and the views are re-rendered?
If you want to follow the pattern you are using, it needs to be handles inside your 'My App' component which gets render in stack navigator. You have to use refs
Go through the following code example to find out how to call Edit function.
import XYZ from './xyz';
export default class MyApp extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: 'myApp',
headerRight: navigation.state.params && navigation.state.params.edit ? (
<View>
<TouchableHighlight
onPress={() => navigation.state.params.edit()}
underlayColor="gray"
>
<View>
<Image source={pencilEditButton} style={styles.navigationButtonImage} />
</View>
</TouchableHighlight>
</View>
) : null,
})
constructor(props) {
super(props);
this.onEdit = this.onEdit.bind(this);
}
componentDidMount() {
this.props.navigation.setParams({ edit: this.onEdit });
}
onEdit() {
if (this.xyz_Ref) {
this.xyz_Ref.Edit();
}
}
render() {
return (
<View>
<XYZ ref={ref => this.xyz_Ref = ref} />
</View>
);
}
}
I am working on a page that basically is supposed to process some back end work and then push on another screen.
This Page should have some text appearing as soon as the page renders that says "submitting your info" then do the backend call, and then the text disappears, and then the whole page performs a push for another screen.
I am confused how to do that !!
This is the render part of the page
render(){
return(
<View style={styles.container}>
<Image style={styles.container} resizeMode="cover" source=
{require('/workingonit.png')}>
<View style={styles.backdropView}>
<Text style={styles.headline}>Submitting your info</Text>
</View>
</Image>
</View>
)
}
I know its something to do with settimeout? or interval?
Sorry I am new to JS and react native .
This example will toggle (hide/show) the text every time you click on the TouchableOpacity by updating the state. You can then, add whatever logic you want as a callback when the state gets updated.
import React from 'react'
import { View, Text, TouchableOpacity } from 'react-native'
export default class DummyPage extends React.Component {
state = {
isTextVisible: false
}
toggleText() {
this.setState({isTextVisible: !this.state.isTextVisible}, () => {
// do some logic here
})
}
renderText() {
if (this.state.isTextVisible) {
return(
<Text>this is a random text</Text>
)
}
}
render() {
return(
<View style={{flex: 1}}>
<TouchableOpacity onPress={this.toggleText}>
<Text>Show Text</Text>
</TouchableOpacity>
{this.renderText()}
</View>
)
}
}
This should work for your API call too. Instead of updating the state with onPress, you can do it when the communication with the backend starts and hide it again when you want to push the user to another screen.