I want to use external web page in my React Native App . I have button on my app and want to open external web page onPress button in my app not on browser.
I have tried WEBVIEW but not helped me.
now I have Tried this :
<HTMLView
value={this.props.html}
onLinkPress={(url) => alert('clicked link: ', url)}
/>
how can i do this ?
I have tried this and its working for me.
install react-native-custom-tabs using this command
npm install react-native-custom-tabs --save
and than link custom tabs package using
react-native link react-native-custom-tabs
and than call it
import {CustomTabs,ANIMATIONS_SLIDE,ANIMATIONS_FADE} from 'react-native-custom-tabs';
openCustomizedCustomTabs() {
this.openGoogle({
toolbarColor: '#607D8B',
enableUrlBarHiding: true,
showPageTitle: true,
enableDefaultShare: true,
animations: ANIMATIONS_SLIDE
});
}
errorOccur() {
this.openGoogle({
//toolbarColor: '607D8B', // <--- Invalid toolbar color.
enableUrlBarHiding: '#607D8B', // <-- Type Error.
})
}
openGoogle(option) {
CustomTabs.openURL('https://www.google.com', option).then((launched: boolean) => {
console.log(`Launched custom tabs: ${launched}`);
}).catch(err => {
console.error(err)
});
}
render(){
return <Button marginTop={10} onPress={() => this.openCustomizedCustomTabs()}>
Custom Tab
</Button>
}
and run app.
function renderNode(node, index, siblings, parent, defaultRenderer) {
if (node.name == 'iframe') {
const a = node.attribs;
const iframeHtml = `<iframe src="${a.src}"></iframe>`;
return (
<View key={index} style={{width: Number(a.width), height: Number(a.height)}}>
<WebView source={{html: iframeHtml}} />
</View>
);
}
}
class Page extends React.Component {
render() {
const htmlContent = `
<div>
<iframe src={this.props.utl} width="360" height="300" />
</div>
return (
<HTMLView value={htmlContent} renderNode={renderNode} />
);
}
}
then use it like:
<Page url="the url here..." />
React Native WebView Component has been Added in new Release to Documentation .
https://facebook.github.io/react-native/docs/webview.html
import React, { Component } from 'react';
import { WebView } from 'react-native';
class MyWeb extends Component {
render() {
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
style={{marginTop: 20}}
/>
);
}
}
Related
Been trying to migrate from react-portal from v2 to v4, due to recent upgrade of React to 16.8.6.
Stucked at Portal, whereby the dialog box doesn't show up even when isOpen=true. Found out that onOpen is not firing. Any suggestion on how should I change the codes?
import * as React from 'react';
import { Portal } from 'react-portal';
import 'dialog-polyfill/dialog-polyfill.css';
import 'dialog-polyfill/dialog-polyfill.js';
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from 'react-mdl';
class Confirm extends React.Component {
onOpen() {
if (!this.dialog.showModal) {
dialogPolyfill.registerDialog(this.dialog);
}
this.dialog.showModal();
}
closeDialog() {
this.dialog.close();
this.portal.closePortal();
}
render() {
const props = this.props;
return (
<Portal ref={c => this.portal = c} onOpen={this.onOpen.bind(this)} isOpen={Boolean(props.callback)} {...props}>
<dialog ref={c => this.dialog = c} className="mdl-dialog" style={props.style}>
<DialogTitle>{props.title}</DialogTitle>
<DialogContent>
{props.message}
</DialogContent>
<DialogActions>
<Button type='button' onClick={() => {this.closeDialog(); props.confirm();}}>Confirm</Button>
<Button type='button' onClick={() => {this.closeDialog(); props.dismissConfirmation();}}>Cancel</Button>
</DialogActions>
</dialog>
</Portal>
);
}
}
export default Confirm;
Expected Result: A confirmation dialog box to pop up.
From browser, already can see the dialog box is there by modifying the css.
Ended up realized it's due to openByClickOn no longer supported. As explained in:
openByClickOn Not Supported In React-Portal v4
I am using Ionic react I have below tabs on the bottom of my app and want to navigate from job and messages to different components associated with tabs on the click of tabs. But the issue is Page do not render on the click of tabs but if I refresh my page then navigation works fine. I don't know what I am missing here.
render() {
const { _token } = this.state;
let isJobActive = Global.myJobActive();
let isMessageActive = Global.messageActive();
let isMoreActive = Global.moreActive();
let isAddJobActive = Global.addJobActive();
return (
<IonReactRouter>
<IonPage>
<Route exact path="/" render={() => <Redirect to="/home" />} />
<IonTabs>
<IonRouterOutlet>
{/* message */}
<Route
path="/messages"
component={WithRouterPath(MessagesHome)}
exact={true}
/>
{/* jobs */}
<Route
path="/add-job"
component={WithRouterPath(PostJob)}
exact={true}
/>
<Route
path="/my-jobs"
component={WithRouterPath(MyJobs)}
exact={true}
/>
<Route
path="/more-option"
component={WithRouterPath(MoreOptions)}
exact={true}
/>
</IonRouterOutlet>
{/* <div className="footer_menu"> */}
<IonTabBar slot="bottom">
<IonTabButton
tab="addjob"
href="/add-job"
onClick={() => {
this.setState({
isJobActive: 0,
isMessageActive: 0,
isMoreActive: 0,
isAddJobActive: 1
});
}}
>
<AddJob isActive={isAddJobActive} />
<IonLabel>Add Job</IonLabel>
</IonTabButton>
<IonTabButton
tab="myjobs"
href="/my-jobs"
onClick={() => {
this.setState({
isJobActive: 0,
isMessageActive: 0,
isMoreActive: 0,
isAddJobActive: 1
});
}}
>
<MyJob isActive={isJobActive} />
<IonLabel>My Jobs</IonLabel>
</IonTabButton>
<IonTabButton
tab="messages"
href="/messages"
onClick={() => {
this.setState({
isJobActive: 0,
isMessageActive: 1,
isMoreActive: 0,
isAddJobActive: 0
});
}}
>
<Message isActive={isMessageActive} />
<IonLabel>My Messages</IonLabel>
</IonTabButton>
<IonTabButton
tab="more-option"
href="/more-option"
onClick={() => {
this.setState({
isJobActive: 0,
isMessageActive: 0,
isMoreActive: 1,
isAddJobActive: 0
});
}}
>
<More isActive={isMoreActive} />
<IonLabel>More</IonLabel>
</IonTabButton>
</IonTabBar>
{/* </div> */}
</IonTabs>
</IonPage>
</IonReactRouter>
);
}
So this is my code when I click any tab it redirects to that URL but didn't render the component.
This all happened after I update ionic version
In my package.json
"#ionic/react": "^4.11.4",
"#ionic/react-router": "^4.11.4",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
and my WithRouterPath component is like below
const WithRouterPath = (WrappedComponent, options = {}) => {
const HOC = class extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
Global.isFooterVisible();
}
componentDidUpdate(prevProps) {
Global.isFooterVisible();
}
render() {
return <WrappedComponent {...this.props} />;
}
};
return HOC;
};
export default WithRouterPath;
I had this issue. I am new to Ionic and React, so I don't really know if this issue is the same as mine, but I will let you know what I found. In my app I had a router setup in the app file that redirected /tabs to a page called mainTabs. The Tabs were actually setup in that mainTabs page. The problem was that in the router settings for redirecting traffic to the tabs page I had "exact={true}" set. This doesn't allow you to pass /tab/* as possibilities. When I took "exact={true}" off the route going to my tabs it fixed it.
I have below webview component, I wanted the link to be opened in a mobile browser app rather than in inside current webview in my app.
return() {
<WebView source={{ html: `Google`}} />
}
This worked for me.
import { WebView, Linking, NavState } from 'react-native';
const html = `
Google
Twitter
`
class WebViewWrapper extends Component {
private webview;
handleNavigationStateChange = (event: NavState) => {
if (event.url) {
this.webview.stopLoading();
Linking.openURL(event.url);
}
};
render() {
return (
<WebView
originWhitelist={['*']}
ref={ref => {
this.webview = ref;
}}
source={{ html }}
onNavigationStateChange={this.handleNavigationStateChange}
/>
);
}
}
you can do this:
import { Linking } from 'react-native';
on you launch function
Linking.openURL( some_url );
For more details, follow this full example: Just what you want
Calling stopLoading freezes the WebView and links may stop working after pressing them once. Better to use onShouldStartLoadWithRequest (API Reference).
So the code could look something like this:
import { Linking } from 'react-native';
import { WebView } from 'react-native-webview';
const html = `
Google
Twitter
`;
const shouldStartLoadWithRequest = (req) => {
// open the link in native browser
Linking.openURL(req.url);
// returning false prevents WebView to navigate to new URL
return false;
};
const MyComponent = () => (
<WebView
originWhitelist={['*']}
source={{ html }}
onShouldStartLoadWithRequest={shouldStartLoadWithRequest}
/>
);
export default MyComponent;
Note that onShouldStartLoadWithRequest behaves a bit differently on iOS.
Try this one. This will save your time and patience :)
import HTML from 'react-native-render-html';
<HTML
html={this.state.content.description}
// imagesMaxWidth={Dimensions.get('window').width}
onLinkPress={(evt, href) => { Linking.openURL(href) }}
/>
Fully supportive of android, ios and Expo too. And has some cool customisations you can try with.
https://www.npmjs.com/package/react-native-render-html
I don't really clear how to implement onMessage and postMessage, can I get whole web page but only from react native side.
I mean, I will inject this code using injectedJavaScript
var markup = document.documentElement.innerHTML
window.postMessage(markup)
and I will receive the result using onMessage. Is it posible cause so far I can't do that
yes you can do this all you to have to do is use window.postMessage("message") from your web-page that is going to load in WebView and you can see that message in onMessage prop.
Example:
class Test extends React.Component{
constructor(props){
super(props);
this.state:{
html:''
}
}
componentWillMount(){
this.setState({
html : `<html>
<head>
<script>
window.postMessage("Messga from webView")
</script>
</head>
<body><h1>Hello from webView</h1></body>
</html>`
})
}
render(){
return (
<View style={{flex: 1}}>
<WebView
ref={(reff) => {
this.webView = reff;
}}
source={{html: this.state.html}}
style={[styles.flex1, styles.padding5]}
onMessage={(event)=>{
let message = event.nativeEvent.data;
/* event.nativeEvent.data must be string, i.e. window.postMessage
should send only string.
* */
}}
onNavigationStateChange={(evt)=>{}}
onError={(e) => {
console.warn('error occured', e)
}}/>
</View>
)
}
}
I just added a sample html and rendered it in WebView, you can do the same in your page that you are going to load in WebView.
Or another solution is:
You can use injectedJavaScript or injectJavaScript props of WebView as described here.
postMessage is deprecated :: and now you have to use window.ReactNativeWebView.postMessage(data)
const injectedJavascript = `(function() {
window.postMessage = function(data) {
window.ReactNativeWebView.postMessage(data);
};
})()`;
for a full imagination of a component will be:
export const WebViewComponent = (props) => {
const webViewScript = `
setTimeout(function() {
window.ReactNativeWebView.postMessage(/*your pushed data back to onMessage 'event.nativeEvent.data'*/);
}, 2500);
true; // note: this is required, or you'll sometimes get silent failures
`;
return (
<WebView
source={{
uri: `https://example.com`,
}}
automaticallyAdjustContentInsets={false}
scrollEnabled={false}
onMessage={(event) => {
// do something with `event.nativeEvent.data`
}}
javaScriptEnabled={true}
injectedJavaScript={webViewScript}
domStorageEnabled={true}
style={{ width: "100%", height: /*webViewHeight*/ }}
/>
);
};
Actually
i was looking at the documentation since i use the injectJavascript function of the react native´s webview. And in here https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage , it says that for extensions we need to use a "*" as a property .
So it wouldn´t be like this "window.postMessage("Messga from webView")"
Instead it will need to be window.postMessage("Messga from webView","*") to work.
I try to implement the hero animation like in the shoutem About extension. Basically, I add animationName to NavigationBar and the Image like in the extension. I also had to add ScrollDriver because it would error-ed otherwise. But it seems the NavigationBar does not pass the driver down to its child components, so I still got this error. Is it possible to implement the hero animation like what was demonstrated here? https://medium.com/shoutem/declare-peace-with-react-native-animations-e947332fa9b1
Thanks,
import { ScrollDriver } from '#shoutem/animation';
getNavBarProps() {
const driver = new ScrollDriver();
return {
hasHistory: true,
driver: driver,
title: 'Title',
navigateBack: () => this.props.navigation.dispatch(NavigationActions.back()),
styleName: 'fade clear',
animationName: 'solidify',
};
}
render () {
const driver = new ScrollDriver();
return (
<Screen styleName=" paper">
<View style={{height:68}}>
<NavigationBar {...this.getNavBarProps()} />
</View>
<ScrollView style={styles.container}>
<Image
styleName="large"
source={require('../Images/spa2.jpg') }
defaultSource={require('../Images/image-fallback.png')}
driver={driver}
animationName="hero"
/>
...
I'm the author of the article, from you question, I'm not sure are you trying to create an extension on shoutem or you just want to recreate animation in any other React Native app.
If you are creating an extension or CardStack from #shoutem/ui/navigation, you don't event need to care for ScrollDriver. It would be pushed throught the context to the ScrollView (imported from #shoutem/ui) and NavigationBar (imported from #shoutem/ui/navigation).
If you are creating your own React Native project to be able to do it like in article I suggest the following. At the root component of your app:
import ScrollView from '#shoutem/ui';
class App extends Component {
...
render() {
return (
<ScrollView.DriverProvider>
<App />
</ScrollView.DriverProvider>
);
}
}
Then you don't have to take care of initialization of ScrollDriver on each screen, if you use our components and a ScrollView it will push the driver where it needs to be. :) So your screen at the end would look like this:
import {
ScrollView,
NavigationBar,
Image
} from '#shoutem/ui';
class MyScreen extends Class {
render() {
return (
<Screen>
<NavigationBar animationName="solidify" />
<ScrollView>
<Image animationName="hero" />
</ScrollView>
</Screen>
);
}
}
The whole working example is here https://github.com/shoutem/ui/tree/develop/examples/RestaurantsApp/app