I need to send request every time when i open page. Currently when i access page first time after load the app everything is ok, but if i go to another page and back after that request is not send it again.
You have to add focus listener so when you go back, It will refresh the data like
import * as React from 'react';
import { View } from 'react-native';
function AppScreen({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// The screen is focused
// Call any action and update data
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [navigation]);
return <View />;
}
source : https://reactnavigation.org/docs/function-after-focusing-screen/
Here you go, example for a class based and functional based component to run something on every load of the screen.
import React, { useEffect } from "react";
import {View} from 'react-native'
//Functional Component
const App = () =>
{
useEffect(() =>
{
myAction();
}, [])
return (
<View>
</View>
);
}
//Class based Component
class App extends Component
{
componentDidMount()
{
this.myAction();
}
render()
{
return(
<View>
</View>
)
}
}
Related
I have an Expo app that will open some web page with a redirect to expo itself. On that case, this is to perform 3DS callbacks. Here is a very simplified version:
import React, {
FC, useEffect, useState,
} from 'react';
import * as Linking from 'expo-linking';
import * as WebBrowser from 'expo-web-browser';
import {
Button,
} from '#private/apps-components';
import {
ButtonProps,
View,
} from 'react-native';
export const MyComponent: FC = () => {
const [loading, setLoading] = useState<boolean>(false);
const urlEventHandler = async (event): Promise<void> => {
console.log('url-event', event);
setLoading(false);
// Stuff...
};
useEffect(() => {
Linking.addEventListener('url', urlEventHandler);
return () => Linking.removeEventListener('url', urlEventHandler);
}, []);
const handlePress: ButtonProps['onPress'] = () => {
setLoading(false);
WebBrowser.openBrowserAsync(aRandomUrlThatWillRedirectToTheApp, {
showInRecents: true,
})
}
return (
<View>
<Button
title="Test"
onPress={handlePress}
loading={loading}
/>
</View>
);
};
export default null;
This is working. However, if the customer close the navigator before the web redirect is being processed, the app is stuck on the loading state.
The question is: How to detect if a user has closed the opened WebBrowser?
Solved this using AppState:
https://reactnative.dev/docs/appstate
if (appState === "active") { // do things after closing the browser }
I haven't actually tested this - could follow up - but you could probably use react-navigation to detect whether the component is in focus or not. IE when you open the web browser, the component is not in focus, but when you close the web browser, the component is back in focus.
For react navigation version 4 you would wrap the component in withNavigationFocus in order to achieve this: https://reactnavigation.org/docs/4.x/function-after-focusing-screen#triggering-an-action-with-the-withnavigationfocus-higher-order-component. For 5, and 5+, you can use the useIsFocused hook: https://reactnavigation.org/docs/5.x/function-after-focusing-screen/#re-rendering-screen-with-the-useisfocused-hook
With Android...when you swipe right on an app, it will unmount all components and cease all app operations. First component to be unmounted appears to be the parent componenet (normally named app.js).....please correct me if Im wrong on this.
When this happens..I know the componentWillUnmount event fires as I added the code below that logs to the console.
componentWillUnmount() {
console.log('app.js....componentWillUnmount');
}
My question is whether I can add some extra code within componentWillUnmount that could Alert the user "are you sure you want to quit app?"....and give them an option so say "no" and keep the app live
The BackHandler API description on the React-Native official docs has the example for the same use case. You can take a look at the given example code snippet on the official docs and pick the example with functional or class based component as per your choice.
You can place that code at the top level component like App.js or Routes.js.
Another approach with the autohide toast can be:
Using functional component
import React, {useEffect, useRef} from 'react';
import {Text, SafeAreaView, BackHandler, ToastAndroid} from 'react-native';
export default function App() {
const doubleBackToExitPressedOnce = useRef(false);
useEffect(() => {
const backAction = () => {
if (doubleBackToExitPressedOnce.current) {
BackHandler.exitApp();
return true;
}
ToastAndroid.show('Press back again to exit', ToastAndroid.SHORT);
doubleBackToExitPressedOnce.current = true;
setTimeout(() => {
doubleBackToExitPressedOnce.current = false;
}, 2000);
return true;
};
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
backAction,
);
return () => backHandler.remove();
}, []);
return (
<SafeAreaView>
<Text>Hello world!</Text>
</SafeAreaView>
);
}
Using class component:
import React, {Component} from 'react';
import {SafeAreaView, Text, BackHandler, ToastAndroid} from 'react-native';
export default class App extends Component {
backAction = () => {
if (this.doubleBackToExitPressedOnce) {
BackHandler.exitApp();
}
ToastAndroid.show('Press back again to exit', ToastAndroid.SHORT);
this.doubleBackToExitPressedOnce = true;
setTimeout(() => {
this.doubleBackToExitPressedOnce = false;
}, 2000);
return true;
};
componentDidMount() {
this.doubleBackToExitPressedOnce = false;
this.backHandler = BackHandler.addEventListener(
'hardwareBackPress',
this.backAction,
);
}
componentWillUnmount() {
this.backHandler.remove();
}
render() {
return (
<SafeAreaView>
<Text>Hello world!</Text>
</SafeAreaView>
);
}
}
I have developed an store app, my boss wants a feature that from wordpress panel select predefined layout to change the whole design and choose which category to be first or .... .
I have created all designs and components that needed, but I do not know how to change app layout that I recieved from api, is there any code or help for that. This change is not about color , its about changing whole home page app layout
Sorry for my english
Here is a simple example that you could implement.
You'll need to create custom complete components for each layout for the homepage.
Then you'll need to call the Wordpress API to get the layout name that needs to be displayed.
import React, { PureComponent } from 'react';
import { AppRegistry } from 'react-native';
import Layout1 from './components/Home/Layout1';
import Layout2 from './components/Home/Layout2';
import Layout3 from './components/Home/Layout3';
import Layout4 from './components/Home/Layout4';
import Loading from './components/Loading';
class HomePage extends PureComponent {
constructor(props) {
super(props);
this.state = {
layout: null
};
}
async componentDidMount() {
const response = await fetch('https://example.com/wp-json/whatever-api-endpoint')
.then(r => r.json());
this.setState({
layout: response
});
}
getContentElement = () => {
switch (this.state.layout) {
case 'layout_1': return <Layout1 />;
case 'layout_2': return <Layout2 />;
case 'layout_3': return <Layout3 />;
case 'layout_4': return <Layout4 />;
default: return <Loading />
}
};
render() {
const contentElement = this.getContentElement();
return (
<View>
{contentElement}
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => HomePage);
In my application, I have few cases where navigation.goBack() cannot be used. I use react-navigation for navigation. When i'm in the detail screen, When I go back, I want to send an API call to get the latest records to the parent screen. So I used, navigation.navigate() instead of navigation.goBack(); But, this makes my app slow if I navigate and navigate back few times. It gets very slow if I do this few more times. What is the reason behind this? How the navigation.navigate() differs from navigation.goBack()?
What is the preferred way of handling this kind of scenario?
is there a way to pass param from navigate.goback() and parent can listen to the params and update its state?
You can pass a callback function as parameter (as mentioned in other answers).
Here is a more clear example, when you navigate from A to B and you want B to communicate information back to A you can pass a callback (here onSelect):
ViewA.js
import React from "react";
import { Button, Text, View } from "react-native";
class ViewA extends React.Component {
state = { selected: false };
onSelect = data => {
this.setState(data);
};
onPress = () => {
this.props.navigate("ViewB", { onSelect: this.onSelect });
};
render() {
return (
<View>
<Text>{this.state.selected ? "Selected" : "Not Selected"}</Text>
<Button title="Next" onPress={this.onPress} />
</View>
);
}
}
ViewB.js
import React from "react";
import { Button } from "react-native";
class ViewB extends React.Component {
goBack() {
const { navigation } = this.props;
navigation.goBack();
navigation.state.params.onSelect({ selected: true });
}
render() {
return <Button title="back" onPress={this.goBack} />;
}
}
Hats off for debrice - Refer to https://github.com/react-navigation/react-navigation/issues/288#issuecomment-315684617
I've got screen 1 from which I navigate to screen 2 using:
navigation.navigate('Screen2')
From this screen, I would like to go to the previous one, which simple:
navigation.goBack()
However I'm wondering how can I pass some data back to Screen1? Something like wouldn't work navigation.goBack({ myData: 'something' }) so I'm wondering what is the recommended way to do this in general?
You can solve it with 2 ways :
1 : Using navigation method
Pass a method when you are calling that screen through navigation :
this.props.navigation.navigate('Screen2', {
onGoBack: this.refresh,
});
refresh=(data)=> {
}
and when you press back, pass data like
this.props.navigation.state.params.onGoBack('123');
this.props.navigation.goBack();
2 : Using redux store
If you are using redux in your application, just update redux store whenever user presses back button, and get store value in previous screen.
You can pass a callback (onSelect) like this:
SCREEN 1
import React from "react";
import { Button, Text, View } from "react-native";
class Screen1 extends React.Component {
state = { selected: false };
onSelect = data => {
this.setState(data);
};
onPress = () => {
this.props.navigate("Screen2", { onSelect: this.onSelect });
};
render() {
return (
<View>
<Text>{this.state.selected ? "Selected" : "Not Selected"}</Text>
<Button title="Next" onPress={this.onPress} />
</View>
);
}
}
SCREEN 2
import React from "react";
import { Button } from "react-native";
class Screen2 extends React.Component {
goBack() {
const { navigation } = this.props;
navigation.goBack();
navigation.state.params.onSelect({ selected: true });
}
render() {
return <Button title="back" onPress={this.goBack} />;
}
}
Using the navigation method
Pass a method when you are calling that screen through navigation :
this.props.navigation.navigate('Screen2', {
onGoBack: this.refresh,
});
refresh=(data)=> {
console.log(data)
}
and when you press back, pass data like
this.props.route.params.onGoBack('123');
this.props.navigation.goBack();
if you're using v2 or newer, another possibility is using the navigate function, providing key / routeName of the route you're going back to and the params. docs: https://reactnavigation.org/docs/en/navigation-actions.html#navigate
yes goback work for going previous screen to ...and show our data call from api ...goBack()