--- tags: CircusStreet --- # The Mobile Modernization Strategy PoC [toc] ## Project structure In this PoC the `react-native` application is initialized (and located) inside the `mobile.circusstreet.com` repository on the top level as below: ``` mobile.circusstreet.com - ... - cordova - htdocs - react-native <- here - mycs - ... ``` ### Assets #### iOS Files that will be used inside react-native app as the inner application must be "dragged and dropped" via xCode into the `cordova` directory. That's way the xCode will link that files in the `react-native/mycs/ios/mycs.xcodeproj/project.pbxproj` file as something like this: ``` 846EB90A239536FE00172915 /* cordova */ = { isa = PBXGroup; children = ( 84C33A1B2397C14000047EB3 /* index2.html */, 84C33A192397C13A00047EB3 /* css */, 84C33A172397C13200047EB3 /* js */, ); path = cordova; sourceTree = "<group>"; }; ``` Therefore, used files don't need to be copied or moved. #### Android On the other hand, for the Android, files must be copied into the specific assets directory: `react-native/mycs/android/app/src/main/assets`. ## Wrapper We use the `WebView` component from the `react-native-webview` library (https://github.com/react-native-community/react-native-webview) as the `WebView` from `react-native` is currently deprecated. The uri of the inner App depends on platform: ``` const uri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'index2.html'; ``` That is used in the `WebView` component: ```javascript <WebView ... source={{uri}} javaScriptEnabled={true} allowFileAccess={true} originWhitelist={['*']} /> ``` ## Comunication We use `PostMessage` API for the comunication between the react-native and inner app (current mycs). ### React Native -> MYCS React Native: ```App.js```: ```javascript <Button title="Increase" onPress={() => { this.webview.postMessage( JSON.stringify({ message: 'MSG_FROM_REACT_NATIVE', data: { counter: this.state.counter + 1, }, }), ); this.increase(); // Update local state }} /> ``` Inner App: ```app.js```: ```javascript function messageHandler(rawData) { var data = JSON.parse(rawData.data); if (data.message === "MSG_FROM_REACT_NATIVE") { ... } } document.addEventListener("message", messageHandler); ... ``` ### MYCS -> React Native Inner App: ```app.js```: ```javascript window.ReactNativeWebView.postMessage( JSON.stringify({ message: "MSG_FROM_WEBVIEW", data: { counter: counter } }) ); ``` Important! Use `window.ReactNativeWebView.postMessage` instead of standard `window.postMessage` API. React Native: ```App.js```: ```javascript const msgHandler = e => { const data = JSON.parse(e.nativeEvent.data); if (data.message === 'MSG_FROM_WEBVIEW') { this.setState({ counter: data.data.counter, }); } }; ... <WebView ... onMessage={msgHandler} /> ``` ### Initial values We can also send initial values to the inner app using the `injectedJavaScript` property of `WebView`: ```javascript <WebView ... injectedJavaScript={` counter = ${this.state.counter}; init(); `} /> ``` ## Debugging The React Native application can be debugged in easy way, using for example React Native Debugger (https://github.com/jhen0409/react-native-debugger). Debugging the inner application can be done as described below. ### iOS You can debug the inner application via Safari Dev Tools, in the `Develop` menu. If you can't see that menu, you need to enable it first, see https://support.apple.com/en-gb/guide/safari/sfri20948/mac. ### Android To be able to debug the inner application you should modify the`MyApplication.java` file as below: ```java ... import android.webkit.WebView; ... public void onCreate() { ... WebView.setWebContentsDebuggingEnabled(true); } ``` Then you will be able to run the inspector via Google Chrome Dev Tools (remote devices section)