SpashScreen React Native - react-native

So Im trying to create a splash screen for my react native app on android and I'm running into a problem where it seems its not able to SpashScreen.hide() due to my aws-amplify withAuthenticator. It just constantly stays on the splash screen
const AppContainer = createAppContainer(App);
class RealApp extends React.Component {
componentDidMount() {
SplashScreen.hide();
}
constructor(props) {
super(props);
}
render() {
return(
<AppContainer></AppContainer>
);
}
}
export default withAuthenticator(RealApp, {
signUpConfig,
usernameAttributes
});
With this it constantly stays on the SplashScreen Image. I then changed it around a little and got rid of the 'WithAuthenticator' like so:
const AppContainer = createAppContainer(App);
export default class RealApp extends React.Component {
componentDidMount() {
SplashScreen.hide();
}
constructor(props) {
super(props);
}
render() {
return(
<AppContainer></AppContainer>
);
}
}
That sort of worked in the sense it showed the SplashScreen then my Amplify Login Page but had the bottom Navbar already rendered with the Login page so could switch to different pages just the amplify login UI was still on the home page etc.

Instead of hide splash screen just navigate your self to another screen with setTimeout function
componentDidMount() {
globalAny.isEditable = true;
if (Constant.isIosDevice()) {
if (CommonTask != undefined) {
CommonTask.getStatusHeight((error: any, events: any) => {
// console.log(events);
Constant.setStatusHeight({
top: events.top,
bottom: events.bottom
});
});
}
} else {
Constant.setStatusHeight({
top: StatusBar.currentHeight,
bottom: 0
});
}
// AsyncStorage.setItem("defaultUserData","0");
setTimeout(() => {
this._token();
}, 3000);
}

Related

How to Reload or Refresh Whole Screen Automatically When user enter in that screen. in react native

I am new to react native. I want To refresh or reload whole screen automatically. when user enter in that screen. Then screen will instantly reload or refresh automatically. So how to do that in react native. is possible . if yes please help.
if I write That logic in componentDidMount Will it reload screen. if yes then How to write that in componentDidMount below.
componentDidMount () {
BackHandler.addEventListener('hardwareBackPress',()=> this.handleBackButtonClick(), false);
}
An often-used hack in React is to change the key prop of your component to force a re-mount of a view:
import { BackHandler } from 'react-native';
class APP extends React.Component {
constructor(props) {
super(props)
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
state = {
uniqueValue: 1;
}
componentWillMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
this.forceRemount();
return true;
}
forceRemount = () => {
this.setState({uniqueValue: this.state.uniqueValue + 1});
}
render() {
return (
<View key={this.state.uniqueValue}>
<Button onPress={this.forceRemount} />
</View>
)
}
}

React native reload child component

I have 2 screen A and Screen B. Screen A has a sub component SomeList which loads data and i just pass the action to the subcomponent and it does the rest.Currently by design of react-navigation no action on revisit. I googled and came across https://reactnavigation.org/docs/en/navigation-events.html but not sure how to use it to reload SomeList when i navigate from ScreenB to ScreenA.
ScreenA
class ScreenA extends Component {
render() {
return (
<SomeList
loadData={this.props.actions.getAlllist}
/>
)
}
ScreenB
Class ScreenB extends Component {
someAction = () => {
this.props.navigation.navigate("ScreenA")
}
}
Due to react-native's design, I think you'd be better off passing data to your child Component.
Here's how you can do this:
class ScreenA extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
}
this.props.navigation.addListener('didFocus', this.load)
this.props.navigation.addListener('willBlur', this.unmount)
}
load = ()=>{
const _data = this.props.actions.getAlllist;
this.setState({data:_data})
}
unmount = ()=>{
this.setState({data:[]})
}
render() {
return (
<SomeList
dataArray ={this.state.data}
/>
)
}
};
If you want to fetch data each time you render something, you can use componentDidMount lifecycle method
class ScreenA extends Component {
state = {
data: [];
}
componentDidMount() {
this.setState({ data: this.props.actions.getAlllist });
}
render() {
return <SomeList loadData={this.state.data}/>;
}
So every time the ScreenA screen it's rendered it will fetch the data.

How do I go back in webview? I am using the react-navigation package in react-native

I installed the react-navigation package in react-native
I have implemented tab navigation and one of them is implemented in webview format.
My problem is that if I press the back physical button on Android, I go from the app itself to the previous tab, not back from the webview.
I've already applied the back button for the webview on the internet, but I have not done that.
I tried to display the onNavigationStateChange log when debugging, but it was not updated when url was moved after it was loaded at first startup. Here is the code I implemented:
import React from "react";
import {BackHandler} from "react-native";
import {WebView} from "react-native-webview";
class SermonScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = {
header: null
};
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
_onNavigationStateChange(navState) {
console.log(navState);
this.setState({
canGoBack: navState.canGoBack
});
}
handleBackButton = () => {
console.log(this.state);
if (this.state.canGoBack === true) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<WebView
source={{uri: 'https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos' }}
ref={(webView) => this.webView = webView}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
/>
);
}
}
export default SermonScreen;
Following the official webview documnentation you could try to do this: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes
In general you were almost there, however the way the YT navigation works made it impossible to be caught via the onNavigationStateChange, that's why we inject a JS code that intercepts these hash changes and posts a message to the parent component, we then catch it inside the onMessage handler and set the state variable properly. Copying the injectedJavaScript and onMessage properties to your example should solve your problem.
I prepared a component for you that seems to do what is needed:
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React, { Fragment } from "react";
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
BackHandler,
StatusBar
} from "react-native";
import { WebView } from "react-native-webview";
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions
} from "react-native/Libraries/NewAppScreen";
class App extends React.Component {
constructor(props) {
super(props);
this.startingUrl =
"https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos";
this.handleBackButton = this.handleBackButton.bind(this);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
console.log(this.state);
const { canGoBack } = this.state;
if (canGoBack) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<Fragment>
<WebView
source={{ uri: this.startingUrl }}
style={{ marginTop: 20 }}
ref={webView => (this.webView = webView)}
injectedJavaScript={`
(function() {
function wrap(fn) {
return function wrapper() {
var res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
window.addEventListener('popstate', function() {
window.ReactNativeWebView.postMessage('navigationStateChange');
});
})();
true;
`}
onMessage={({ nativeEvent: state }) => {
if (state.data === "navigationStateChange") {
// Navigation state updated, can check state.canGoBack, etc.
this.setState({
canGoBack: state.canGoBack
});
}
}}
/>
</Fragment>
);
}
}
export default App;
The response above was perfect. I set the state true for canGoBack though; I was getting a null error, so:
constructor(props) {
super(props);
this.startingUrl = "https://app.vethorcardpag.com.br/GIF/login/0/";
this.state = {
canGoBack : true
}
this.handleBackButton = this.handleBackButton.bind(this);
}
Here is a simple solution using the magic of React's State.
Hope this helps.
import React, { useRef, useState } from 'react'
export default function Component () {
// This is used to save the reference of your webview, so you can control it
const webViewRef = useRef(null);
// This state saves whether your WebView can go back
const [webViewcanGoBack, setWebViewcanGoBack] = useState(false);
const goBack = () => {
// Getting the webview reference
const webView = webViewRef.current
if (webViewcanGoBack)
// Do stuff here if your webview can go back
else
// Do stuff here if your webview can't go back
}
return (
<WebView
source={{ uri: `Your URL` }}
ref={webViewRef}
javaScriptEnabled={true}
onLoadProgress={({ nativeEvent }) => {
// This function is called everytime your web view loads a page
// and here we change the state of can go back
setWebViewcanGoBack(nativeEvent.canGoBack)
}}
/>
)
}
Original answer
https://stackoverflow.com/a/74500469/7823800

React Navigation: Share state between two screens within TabNavigator

I'm learning react native by building a simple chat app. I have two screens wrapped in a TabNavigator where the first screen (Screen A) being the chatbox, and the other screen (Screen B) which displays a list of online users. I'm using SocketIO to fetch these users.
Problem is, how can I access the "onlineUsers" state from ScreenA to ScreenB so I can see an updated list of online users whenever I receive a "user joins" event?
Screen A:
export default class ScreenA extends Component {
constructor(props) {
super(props);
this.state = {
onlineUsers = [];
}
}
componentDidMount() {
// Update list of online users when new user joins chat
this.socket.on('user joins', (payload) => {
this.setState({
onlineUsers: payload.users
})
})
}
}
Screen B:
export default class ScreenB extends Component {
constructor(props) {
super(props);
// I want to get the onlineUsers from ScreenA
this.state = {
onlineUsers = [];
}
}
}
Router:
export const Chat = TabNavigator({
ChatBox: {
screen: ScreenA
},
OnlineUsers: {
screen: ScreenB
},
})
PS: I'm using react-navigation to handle navigation
Best way is to handle events in the parent component and then passing it to their children components. So in your case, you should have a online user list in your router. Then pass the array to screen B. Here is how you should do
Router
state = {
online_users:[]
}
_update = (data) => {
this.setState({online_users:data});
};
export const Chat = TabNavigator({
ChatBox: {
screen: <ScreenA onUpdate={this._update}/>
},
OnlineUsers: {
screen: <ScreenB userList={this.state.online_users}>
},
})
Screen A
export default class ScreenA extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
// Update list of online users when new user joins chat
this.socket.on('user joins', (payload) => {
this.props.onUpdate(payload.users)
})
}
}
Screen B
export default class ScreenB extends Component {
constructor(props) {
super(props);
}
// You can access online user using this.props.userList
}
I came across this post when I ran into a similar issue earlier this year so I thought I'd post my solution.
I would say your best bet in this situation is to use a Custom Navigator to wrap your TabNavigator which will expose <TabNavigator /> in your custom navigator allowing you to pass any methods or state down to ScreenA and ScreenB as screenProps.
The custom navigator would look like:
import React from 'react'
import { ChatTabNavigator } from './ChatTabNavigator'
class StateManagingCustomNavigator extends React.Component {
static router = ChatTabNavigator.router
state = {
onlineStatus: [theStatus]
}
handleMessagePosted = () => {
// Handle message post, etc...
}
// ... SocketIO code and other logic to manage the state here? ...
render() {
const { navigation } = this.props
const { onlineStatus } = this.state
return (
<ChatTabNavigator
screenProps={{
theStatus: onlineStatus,
chatMessagePosted: this.handleMessagePosted
}}
navigation={navigation}
/>
)
}
}
export default StateManagingCustomNavigator
From here you could implement an event system as #Ashish Prakash suggested, or manage all of your state in the custom navigator and transform ScreenA and ScreenB into presentational components.
Use this.props.navigation.setParam({onlineUsers: onlineUsers: payload.users}) when you get user-list from server.
Then use it in Screen B like this.props.navigation.state.params.onlineUsers

React Native Change Page after 5 seconds

I'm newbie in react native and I don't know how to change page after 5 seconds.
I create an android.index.js file that will navigate to LandingPage.js. What I want to do is, when the LandingPage being loaded, it will wait for 5 seconds and then redirect / navigate to another page.
index.android.js
export default class DefaultProject extends Component {
render() {
return (
<Navigator
renderScene={(route, navigator) =>
<LandingPage/>
}
/>
)
LandingPage.js
export default class LandingPage extends Component {
render() {
return (
<Image source={require('./images/event3.jpeg')}
style={styles.container} />
//How to redirect to another page from here after 5 secs?
);
}
}
You can use a simple setTimeout, as you would in a standard JS setup:
export default class LandingPage extends Component {
componentDidMount(){
// Start counting when the page is loaded
this.timeoutHandle = setTimeout(()=>{
// Add your logic for the transition
}, 5000);
}
componentWillUnmount(){
clearTimeout(this.timeoutHandle); // This is just necessary in the case that the screen is closed before the timeout fires, otherwise it would cause a memory leak that would trigger the transition regardless, breaking the user experience.
}
render() {
return (
<Image source={require('./images/event3.jpeg')}
style={styles.container} />
//How to redirect to another page from here after 5 secs?
);
}
}
I'm using lodash for this:
export default class Splash extends React.Component {
constructor(props) {
super(props);
}
async componentWillMount() {
_.delay(() => this.props.navigator.replace({ component: 'login' }), 1000);
}
render() {
return (
...
);
}
}
This will only work if you have a Navigator set up. Check this article:
React Native Navigator — Navigating Like A Pro in React Native