forked from gronxb/webview-bridge
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: example react-navigation (gronxb#30)
* chore: example react-navigation * docs: example guide
- Loading branch information
Showing
74 changed files
with
4,004 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
# Example React Navigation | ||
|
||
This guide covers how to declare state in React Native and share it with the web. | ||
|
||
<video width="320" height="240" muted autoplay loop> | ||
<source src="/react-navigation.mp4" type="video/mp4"> | ||
</video> | ||
|
||
Example: [react-navigation](https://github.com/gronxb/webview-bridge/tree/main/example/react-navigation) | ||
|
||
|
||
## React Native Part | ||
|
||
```tsx | ||
// This file is App.tsx | ||
import React from "react"; | ||
|
||
import { NavigationContainer } from "@react-navigation/native"; | ||
import { createNativeStackNavigator } from "@react-navigation/native-stack"; | ||
import type { NativeStackScreenProps } from "@react-navigation/native-stack"; | ||
import { View, Text, Button } from "react-native"; | ||
import { WebView, navigationRef } from "./src/bridge"; | ||
import { RootStackParamList } from "./src/navigation"; | ||
|
||
function WebViewHomeScreen() { | ||
return ( | ||
<View style={{ height: "100%" }}> | ||
<WebView | ||
source={{ | ||
uri: "http://localhost:5173", | ||
}} | ||
style={{ height: "100%", flex: 1, width: "100%" }} | ||
/> | ||
</View> | ||
); | ||
} | ||
|
||
function UserInfoScreen({ | ||
navigation, | ||
route, | ||
}: NativeStackScreenProps<RootStackParamList, "UserInfo">) { | ||
const { userId } = route.params; | ||
|
||
return ( | ||
<View style={{ height: "100%" }}> | ||
<Text>UserId: {userId}</Text> | ||
|
||
<Button | ||
title="New WebView" | ||
onPress={() => navigation.push("WebViewHome")} | ||
/> | ||
<Button title="Go back" onPress={() => navigation.goBack()} /> | ||
</View> | ||
); | ||
} | ||
|
||
const Stack = createNativeStackNavigator<RootStackParamList>(); | ||
|
||
function App(): JSX.Element { | ||
return ( | ||
<NavigationContainer ref={navigationRef}> | ||
<Stack.Navigator initialRouteName="WebViewHome"> | ||
<Stack.Screen name="WebViewHome" component={WebViewHomeScreen} /> | ||
<Stack.Screen name="UserInfo" component={UserInfoScreen} /> | ||
</Stack.Navigator> | ||
</NavigationContainer> | ||
); | ||
} | ||
|
||
export default App; | ||
|
||
``` | ||
|
||
```tsx | ||
// This file is src/bridge.ts | ||
|
||
import { | ||
StackActions, | ||
createNavigationContainerRef, | ||
} from "@react-navigation/native"; | ||
import { createWebView, bridge } from "@webview-bridge/react-native"; | ||
import InAppBrowser from "react-native-inappbrowser-reborn"; | ||
import { RootStackParamList } from "./navigation"; | ||
|
||
export const navigationRef = createNavigationContainerRef<RootStackParamList>(); | ||
|
||
export const appBridge = bridge({ | ||
async getMessage() { | ||
return "I'm from native" as const; | ||
}, | ||
async openInAppBrowser(url: string) { | ||
if (await InAppBrowser.isAvailable()) { | ||
await InAppBrowser.open(url); | ||
} | ||
}, | ||
async canGoBack() { | ||
return Boolean( | ||
navigationRef.current?.isReady() && navigationRef.current.canGoBack(), | ||
); | ||
}, | ||
async goBack() { | ||
if (navigationRef.current?.isReady()) { | ||
navigationRef.current.goBack(); | ||
} | ||
}, | ||
async navigate<RouteName extends keyof RootStackParamList>( | ||
name: RouteName, | ||
params: RootStackParamList[RouteName], | ||
) { | ||
if (navigationRef.current?.isReady()) { | ||
navigationRef.current.navigate(name as any, params as any); | ||
} | ||
}, | ||
async push<RouteName extends keyof RootStackParamList>( | ||
name: RouteName, | ||
params: RootStackParamList[RouteName], | ||
) { | ||
if (navigationRef.current?.isReady()) { | ||
navigationRef.current.dispatch(StackActions.push(name, params)); | ||
} | ||
}, | ||
async replace<RouteName extends keyof RootStackParamList>( | ||
name: RouteName, | ||
params: RootStackParamList[RouteName], | ||
) { | ||
if (navigationRef.current?.isReady()) { | ||
navigationRef.current.dispatch(StackActions.replace(name, params)); | ||
} | ||
}, | ||
async popToTop() { | ||
if (navigationRef.current?.isReady()) { | ||
navigationRef.current.dispatch(StackActions.popToTop()); | ||
} | ||
}, | ||
}); | ||
|
||
// It is exported via the package.json type field. | ||
export type AppBridge = typeof appBridge; | ||
|
||
export const { WebView, linkWebMethod } = createWebView({ | ||
bridge: appBridge, | ||
debug: true, | ||
fallback: (method) => { | ||
console.warn(`Method '${method}' not found in native`); | ||
}, | ||
}); | ||
|
||
``` | ||
|
||
|
||
|
||
## Web (React) Part | ||
```tsx | ||
// This file is App.tsx | ||
import { useState } from "react"; | ||
import { linkBridge } from "@webview-bridge/web"; | ||
import type { AppBridge } from "@webview-bridge-example-react-navigation/react-native"; | ||
|
||
const bridge = linkBridge<AppBridge>({ | ||
throwOnError: true, | ||
onReady: () => { | ||
console.log("bridge is ready"); | ||
}, | ||
}); | ||
|
||
function App() { | ||
const [userId, setUserId] = useState(""); | ||
|
||
return ( | ||
<div> | ||
<h3>This is a web page.</h3> | ||
|
||
<div | ||
style={{ | ||
display: "flex", | ||
flexDirection: "column", | ||
gap: "12px", | ||
}} | ||
> | ||
<button | ||
onClick={() => { | ||
if (bridge.isNativeMethodAvailable("openInAppBrowser") === true) { | ||
bridge.openInAppBrowser( | ||
"https://github.com/gronxb/webview-bridge", | ||
); | ||
} | ||
}} | ||
> | ||
open InAppBrowser | ||
</button> | ||
|
||
<input | ||
type="text" | ||
style={{ | ||
fontSize: "16px", | ||
}} | ||
value={userId} | ||
onChange={(e) => setUserId(e.target.value)} | ||
placeholder="please userId" | ||
/> | ||
<button | ||
onClick={() => { | ||
bridge.push("UserInfo", { userId }); | ||
}} | ||
> | ||
Go UserInfo | ||
</button> | ||
|
||
<button | ||
onClick={async () => { | ||
if (await bridge.canGoBack()) { | ||
bridge.goBack(); | ||
} else { | ||
alert("Can't go back"); | ||
} | ||
}} | ||
> | ||
Go Back | ||
</button> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default App; | ||
``` |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
BUNDLE_PATH: "vendor/bundle" | ||
BUNDLE_FORCE_RUBY_PLATFORM: 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
module.exports = { | ||
root: true, | ||
extends: '@react-native', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# Xcode | ||
!**/*.xcodeproj | ||
!**/*.pbxproj | ||
!**/*.xcworkspacedata | ||
!**/*.xcsettings | ||
!**/*.xcscheme | ||
*.pbxuser | ||
!default.pbxuser | ||
*.mode1v3 | ||
!default.mode1v3 | ||
*.mode2v3 | ||
!default.mode2v3 | ||
*.perspectivev3 | ||
!default.perspectivev3 | ||
xcuserdata | ||
*.xccheckout | ||
*.moved-aside | ||
DerivedData | ||
*.hmap | ||
*.ipa | ||
*.xcuserstate | ||
project.xcworkspace | ||
**/.xcode.env.local | ||
|
||
# Gradle | ||
/build/ | ||
/packages/react-native-gradle-plugin/build/ | ||
/packages/rn-tester/build | ||
/packages/rn-tester/android/app/.cxx/ | ||
/packages/rn-tester/android/app/build/ | ||
/packages/rn-tester/android/app/gradle/ | ||
/packages/rn-tester/android/app/gradlew | ||
/packages/rn-tester/android/app/gradlew.bat | ||
/ReactAndroid/build/ | ||
/ReactAndroid/.cxx/ | ||
/ReactAndroid/gradle/ | ||
/ReactAndroid/gradlew | ||
/ReactAndroid/gradlew.bat | ||
/ReactAndroid/external-artifacts/build/ | ||
/ReactAndroid/external-artifacts/artifacts/ | ||
/ReactAndroid/hermes-engine/build/ | ||
/ReactAndroid/hermes-engine/.cxx/ | ||
/template/android/app/build/ | ||
/template/android/build/ | ||
|
||
# Buck | ||
.buckd | ||
buck-out | ||
/.lsp.buckd | ||
/.lsp-buck-out | ||
/ReactAndroid/src/main/jni/prebuilt/lib/ | ||
/ReactAndroid/src/main/gen | ||
|
||
# Android Studio | ||
.project | ||
.settings | ||
.classpath | ||
|
||
# Watchman | ||
.watchmanconfig | ||
|
||
# Android | ||
.idea | ||
.gradle | ||
local.properties | ||
*.iml | ||
!/android/README.md | ||
key.properties | ||
|
||
# Node | ||
node_modules | ||
*.log | ||
.nvm | ||
package-lock.json | ||
|
||
# OS X | ||
.DS_Store | ||
|
||
# Test generated files | ||
/ReactAndroid/src/androidTest/assets/AndroidTestBundle.js | ||
*.js.meta | ||
|
||
/coverage | ||
/third-party | ||
|
||
# Test Reports | ||
/reports | ||
|
||
# Stack Dumps generated when programs crash (Ex. bash.exe.stackdump on Win) | ||
*.stackdump | ||
|
||
# Root dir shouldn't have Xcode project | ||
/*.xcodeproj | ||
|
||
# ReactCommon subdir shouldn't have Xcode project | ||
/ReactCommon/**/*.xcodeproj | ||
|
||
# Libs that shouldn't have Xcode project | ||
/Libraries/FBLazyVector/**/*.xcodeproj | ||
/Libraries/RCTRequired/**/*.xcodeproj | ||
/React/CoreModules/**/*.xcodeproj | ||
/React/FBReactNativeSpec/**/*.xcodeproj | ||
/packages/react-native-codegen/**/*.xcodeproj | ||
|
||
# Ruby Gems (Bundler) | ||
/vendor | ||
/template/vendor | ||
|
||
# iOS / CocoaPods | ||
Pods | ||
build | ||
/template/ios/build/ | ||
/template/ios/Pods/ | ||
/template/ios/Podfile.lock | ||
/packages/rn-tester/Gemfile.lock | ||
|
||
# Ignore RNTester specific Pods, but keep the __offline_mirrors__ here. | ||
/packages/rn-tester/Pods/* | ||
!/packages/rn-tester/Pods/__offline_mirrors_hermes__ | ||
!/packages/rn-tester/Pods/__offline_mirrors_jsc__ | ||
|
||
# @react-native/codegen | ||
/React/FBReactNativeSpec/FBReactNativeSpec | ||
/packages/react-native-codegen/lib | ||
/packages/react-native-codegen/tmp/ | ||
/ReactCommon/react/renderer/components/rncore/ | ||
/packages/rn-tester/react-nativeModuleExample/ScreenshotManagerSpec* | ||
|
||
|
||
# Additional SDKs | ||
/sdks/download | ||
/sdks/hermes | ||
/sdks/hermesc | ||
|
||
# Android memory profiler files | ||
*.hprof | ||
|
||
# Temporary files created by Metro to check the health of the file watcher | ||
.metro-health-check* |
Oops, something went wrong.