React Navigation: Pushing to stack in a React Native Webview - react-native

I have a Component that renders a Webview, of which there are links. For example, if I have something like:
export const About = () => {
return (
<SafeAreaView edges={['right', 'top', 'left']} style={{ flex: 1 }}>
<Webview url={`${BASE_URL}/about`} />
</SafeAreaView>
)
}
export default About
Let's say that on the /about page, we have a link to /faq. As things currently stand, if I click on the link to /faq, the page will be rendered in that current Webview.
My desired behavior is for the /faq to put on the navigation stack so I can take advantage of the back button in the header. I don't know how to accomplish this. I don't have access to the link to /faq via React Native (see code snippet above) so I can't just add an onClick that pushes a page to the stack.
Another thing I was exploring was setting up some linking configurations so I can link /faq to /about, and so the routing would recognize that. No idea if I was going down a good path there. Please forgive me if I've mixed up concepts, my understanding of the React Native ecosystem and React Navigation is still very raw. Thank you for your time.

Related

React native getInitialURL not nullify after use

After using Linking.getInitialURL() the URL stay there.
I am using react-native-router-flux to navigate.
when users log out I run
import { NativeModules } from 'react-native';
NativeModules.DevSettings.reload()
What happens is the react-navigation do Linking.getInitialURL()
and if there any result so it navigates automatically to the page.
how to reset Linking.getInitialURL() after use ?
happens only on android
React Navigation 5 provides an option to specify a custom getInitialURL method which you can use:
<NavigationContainer
linking={{
// ... linking config
getInitialURL() {
return YourCustomModule.getInitialURL();
},
}}
>
{/* content */}
</NavigationContainer>
https://reactnavigation.org/docs/navigation-container/#linkinggetinitialurl
For the implementation, since you're reloading the whole JS, the code cannot be in JS as the state is lost on reload. You'll need to write a custom native module where you can clear the initial URL when reloading.

Splash Screen not visible from AppLoading

import React from "react";
import AppLoading from "expo-app-loading";
export default function App() {
return <AppLoading />;
}
Isn't the above code supposed to show the splash screen to me? All I get is a white screen. Would really appreciate knowing what I did wrong here.
I have splash.png in my assets folder.
My app.json file:
{
"expo": {
...
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#e2fcff"
},
...
}
}
The code you have shown looks fine. However, there's more to it.
It's quite unclear to me what is actually supposed to work and not. For me, who runs a custom-managed workflow, AppLoading works when I prebuild android/ios and run the standalone app. When I run in Expo Go app I simply see a blank screen instead of the splash screen.
People have discussed if AppLoading works in bare workflow and according to Expo's sdk it should. It also works for me with a prebuild, so bare workflow is supported (in Expo SDK 42).
I have seen no mentions about showing a splash screen within the Expo Go app though, so can't tell whether that is supported or not.
And then web... Once again, not sure if it should work or not - it doesn't for me. It shows a blank page while loading. And in the fonts guide there is an Expo snack which uses AppLoading that shows a splash screen on Android but merely a blank page on web. The AppLoading docs claims it has support for web. If that means it won't crash, or actually display a splash screen image is left untold. The AppLoading docs further claims it uses SplashScreen to show the splash screen, which doesn't have web support. So, I suppose there's nothing such a splash screen for web (which wouldn't surprise me, because splash screens are uncommon on web).
Personally, I'm fine with Android/iOS support for standalone apps. I only use Expo Go for testing. Furthermore, the splash screen I will use for mobile devices won't work well on web anyway. The skeleton I will show won't look the same as the web version, so I would rather implement at custom splash screen for web.
Summary for AppLoading support:
Managed and bare workflow are both supported.
It works on standalone apps.
Not sure if it will display the splash screen in Expo Go app.
Web appears to fallback to displaying a blank page.
If I'm wrong somewhere, or if someone knows if AppLoading works in Expo Go App, please fill me in!
App loading documentation In the documentation, it says that you need to provide additional arrugments
export default function App() {
const [isLoading, setLoading] = useState(true);
if (isLoading) {
return(
<AppLoading
startAsync={() => console.log('starting')}
onFinish={() => { setTimeout(() => {setLoading(false)}, 1000) }}
onError={(err) => {console.log(err)}}
/>
)
}
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}

Building React Navigation v5 stack with Stack Navigation and Tab Navigation

I'm currently attempting to get my head round how to build out my React Navigation stack with v5, and not using a switchNavigator.
My basic app structure is such (will post an image of a flow below):
check Auth
-> signed in yes
-> tab navigation (with stack navigators nested within)
-> signed in no
-> nested stack navigator
But I just can't figure out how I should build the root of my app. I don't know how to combine my tab navigator and stack navigator together to make my app function from start to finish.
(It's worth noting, the 'check Auth' is an actual screen, not a conditional)
Here's my illustration showing my project layout:
Can someone advise please how I can build this out? Any tips or general structure / advice on how best to do it would be really appreciated!
So what I've typically done in the past is the render either or, not both. So as an example, the root navigation could look as follows:
import { NavigationContainer as RootNavigationContainer } from "#react-navigation/native";
const Navigation = () => {
const { someToken } = useContext(SomeContext);
return (
<RootNavigationContainer>
{!someToken ? <AuthStack /> : <MainStack />}
</RootNavigationContainer>
);
};
The determining of the user's authenticated state should be done while the Splash Screen is being shown, using a separate component just confuses the flow IMO. If the user is authenticated, you can set some state (in the example a token is set on the context) which will then drive which navigation stack is shown.
In my example, AuthStack would contain all of the screens where you user is unauthenticated - so your login, registration etc. MainStack would contain the screens that should only be shown to authenticated users.
Things like FaceID should be included in your Login flow.

webview onNavigationStateChange returns url of previous page

In react native webview, when I navigate to a page the onNavigationStateChange returns url of the previous page? I think its an issue and posted it to github react native issues.
<WebView
ref={r => this.webview = r}
style = {{marginTop : 0}}
onNavigationStateChange=
{this._onNavigationStateChange.bind(this)}
startInLoadingState = {true}
source = {{uri: 'https://www.youtube.com' }}
/>
_onNavigationStateChange(webViewState)
{
this.setState(
{
youtube_video_url: webViewState.url
})
}
When I print this youtube_video_url, it is of the previous page or previous browsed video.
Sadly, all the webview methods like onNavigationStateChange, onLoad, onLoadStart etc are not working as expected in cases of single page application websites or websites that don't trigger a window.load event.
Normaly onNavigationStateChange gets triggered in the beginning of a request with {loading: true, url: "someUrl", ...} and once after the loading of the url with {loading: false, url: "someUrl", ...}.
There is no global workaround (to my knowledge) that will work correctly for all websites and for both iOs/Android but maybe this can help in your case:
https://snack.expo.io/H1idX8vpM
Basically you inject a custom javascript in the webview that notifies the WebView which is the loaded page. You can enhance it if you want to catch custom window.history manipulation events.

how to use react-native-web and react-navigation together and access from web url

UPDATE:
react-navigation web support is done. follow this:
https://reactnavigation.org/docs/en/web-support.html
ORIGIN:
I try to share my code between react-native and web.
when I try react-native-web, it works well.
but there is only one question, how to access the specific screen from URL?
I read the react-navigation docs, there nothing about that.
and react-router-native can catch the web URL,
but it has navigator likes StackNavigator/DrawerNavigator.
and idea about that?
I'm not sure what the case was at the time you posted this question, but you definitely can use react-navigation with web now adays.
Now with Linking we can Handle deep links in React Native apps on Android and iOS, plus
Enable URL integration in browser when using on web.
The NavigationContainer component takes in a linking prop which allows you to map out your routes.
const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
Profile: 'user',
},
},
};
function App() {
return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
{/* content */}
</NavigationContainer>
);
}
Once we establish what all of the routes or "links" are in our app we can start using Link components to navigate just like in a normal react web application if you used react-router-dom.
import { Link } from '#react-navigation/native';
// ...
function Home() {
return <Link to="/profile/jane">Go to Jane's profile</Link>;
}
These link components should work on both mobile, and web versions.
https://reactnavigation.org/docs/configuring-links/
https://reactnavigation.org/docs/deep-linking/
https://reactnavigation.org/docs/link
I don't think it's possible as ReactNavigation is using an internal state object. Remember, it's mobile framework, it has no concept of URL routing.
I also wanted to point out that even though RN claims web support you will need to be careful with component selection as not all the behaviours are identical (from memory, FlatList does not support touch scroll)