WebView inconsistently showing white screen react-native - react-native

I'm using a WebView to show an iframe of a twitch-stream in my react-native app, however at some points when it renders the WebView only shows up as a blank white screen until you scroll/move the UI and at other times it works as intended.
There are no errors emitted when the WebView is blank, it seems to load as intended so not really sure why it just shows a blank white screen.
Here is the WebView code:
<Animated.View
style={{
height: anim,
width: width,
overflow: 'hidden',
}}
>
<WebView
onLoadEnd={() => {
useAnimation()
}}
source={{
uri: `https://host.com/iframe/?channel=${channelName}`,
}}
style={{
height: heightByRatio,
width: width,
flex: 0,
}}
mediaPlaybackRequiresUserAction={false}
allowsInlineMediaPlayback={true}
/>
</Animated.View>

I had a very similar issue of webviews sometimes loading blank on android devices. I can't say I figured out why it was happening, but I solved it by delaying the load of the webview and putting a 2px border around the container wrapping the webview. Neither solution worked on its own, both were needed.
export default class WebviewExample extends Component<Props> {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
setTimeout(() => {
this.setState({loadWebview: true});
});
}
render() {
return (
<View style={styles.view}>
{this.state.loadWebview &&
<WebView />
}
</View>
);
}
}
const styles = StyleSheet.create({
view: {
borderWidth: 2,
borderColor: 'transparent',
}
});

Related

width and height behavior different in web and ios

I am new in the react native ecosystem. I am developing a react native app with expo and I see some things weirds.
My simple code is:
export function Practical({ navigation }: any): JSX.Element {
return (
<View>
<View style={styles.primro}>
<View style={styles.ultimo}>
<Text>Hola</Text>
</View>
</View>
</View>
);
}
const yellow = 'yellow';
const purple = 'purple';
const styles = StyleSheet.create({
primro: {
backgroundColor: yellow,
height: '141px',
width: '341px',
},
ultimo: {
backgroundColor: purple,
height: '100px',
width: '200px',
},
});
I am seeing this in web:
I see this in ios:
And this is what I see in chrome with the iphone view, and I would expect to see in the xcode simulator:
Thanks!!
I tried with several structures.

Navigation using images nested inside Touchable Opacity

Background:
I've designed a custom footer for my app in React Native, I've set some images to act as icons. I'm trying to have them redirect to other pages of the app upon touch.
What I have tried
I've been trying to use the same images nested within TouchableOpacity components to have them redirect to other pages using react navigation.
This is my code:
export class Footer extends React.Component {
render (){
return (
<View style = { styles.footStyle } >
<TouchableOpacity onPress={ () => navigation.push('Home')} >
<Image
style = { styles.iconStyle }
source = {require('./img/home.png')}/>
</TouchableOpacity>
<TouchableOpacity onPress={ () => navigation.push('Favoritos')} >
<Image
style = { styles.iconStyle }
source = {require('./img/heart.png')}/>
</TouchableOpacity>
<TouchableOpacity onPress={ () => navigation.push('Search')} >
<Image
style = { styles.iconStyle }
source = {require('./img/search.png')}/>
</TouchableOpacity>
<TouchableOpacity onPress={ () => navigation.push('Notifications')} >
<Image
style = { styles.iconStyle }
source = {require('./img/bell.png')}/>
</TouchableOpacity>
<TouchableOpacity onPress={ () => navigation.push('Help')} >
<Image
style = { styles.iconStyle }
source = {require('./img/circle.png')}/>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
footStyle: {
paddingBottom: 0,
paddingRight: 10,
backgroundColor: '#ffffff',
flex: 0.4,
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: '#000000'
},
iconStyle: {
flex: 0.2,
height: undefined,
width: undefined
}
})
Problem
When I try and run the app in expo, the images are not rendering at all. I get my blank footer without any content. I've tried touching the footer to see if the images weren't rendering but the "button" actually worked, that didn't work.
Question
How exactly can I nest an image within a TouchableOpacity component? Is it even possible to use this method with React Navigation?
Thanks a lot!
For an Image component to work you should provide a height and width in style.
Here you are setting it as undefined
Try something like
iconStyle: {
flex: 0.2,
height: 100,
width: 100
}
Also on the navigation, you will have to pass the navigation prop to the Footer. As its a class you should access it as this.props.navigation.navigate()
As your code for integrating the Footer is not here, its hard to comment on how to pass the prop to the footer.

How to show loading icon in react native until the API response in react native?

I am creating a new app. After tapping the submit button I want to show the loading icon in the login page until the API response. Please help me
First create a state variable for showing and hiding loader as follows
this.state = {
..
loading: false,
..
};
In the api call before the request send, you can set loading state to true and after completing the response set it to false
getData() {
this.setState({loading:true});// For showing loader
axios.get('api_link_goes_here')
.then(response => {
this.setState({loading:false});// For hiding loader
console.log(response.data);
})
.catch(error => {
this.setState({loading:false});// For hiding loader
console.log(error);
});
}
In your render template, you can add a View for showing the loader based on the state, You can add it to the bottom and position and make it full screen to avoid further clicks until response is received
render() {
return (
<View style={container}>
.....
{this.state.loading === true &&
<View style={styles.myloader}>
<CustomLoader /> // You can define this in another component or simply write <Text>Please wait...</Text>
</View>
}
....
</View>
)}
Style is given below for loader container
const styles = StyleSheet.create({
.....
myloader: {
position: "absolute",
top: 0,
left: 0,
zIndex: 10,
backgroundColor: "#ffffff",
opacity: 0.9,
justifyContent: 'center',
alignItems: 'center',
width: "100%",
height: "100%"
}
...
});

How do I prevent a user clicking through an overlay?

I have an overlay positioned absolute, it has backgroundColor and it covers the whole screen. It's overlaying several button components which I can still click on through the overlay.
How do I prevent this behavior? I want to swallow all click events landing on the overlay first.
Code:
// Overlay
export default class Overlay extends Component {
render() {
return (
<View style={styles.wrapper} />
);
}
}
const styles = StyleSheet.create({
wrapper: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
backgroundColor: "black",
opacity: 0.7
}
});
// Container
export default class Container extends Component {
render() {
return (
<View>
<Overlay />
<Button onPress={() => this.doSomething()}>
<Text>Hello</Text>
</Button>
</View>
);
}
}
Write the absolute position component after other components to render it over the other components.
export default class Container extends Component {
render() {
return (
<View>
<Button onPress={() => this.doSomething()} title="Hello" />
<Overlay /> // provide appropriate height and width to the overlay styles if needed...
</View>
);
}
}
Solution 1- You can try to use Modal component from react-native
Solution 2- Wrap TouchableWithoutFeedback having blank onPress around your overlay. Don't forget to give full height and width to TouchableWithoutFeedback
something like
<TouchableWithoutFeedback>
<Overlay/>
<TouchableWithoutFeedback/>

React Native Webview not loading any url (React native web view not working)

I am trying to implement react native webview component in my application, but the web view is not loading any url its just showing the white page.
var React = require('react-native');
var{
View,
Text,
StyleSheet,
WebView
} = React;
module.exports = React.createClass({
render: function(){
return(
<View style={styles.container}>
<WebView source={{uri: 'https://m.facebook.com'}} style= {styles.webView}/>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex:1,
backgroundColor: '#ff00ff'
},webView :{
height: 320,
width : 200
}
});
Below is the screenshot of the output .
I had this issue. WebView would render when it was the only component returned, but not when nested in another View component.
For reasons I'm not entirely sure of the issue was resolved by setting a width property on the WebView component.
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<WebView
source={{uri: 'https://www.youtube.com/embed/MhkGQAoc7bc'}}
style={styles.video}
/>
<WebView
source={{uri: 'https://www.youtube.com/embed/PGUMRVowdv8'}}
style={styles.video}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'space-between',
},
video: {
marginTop: 20,
maxHeight: 200,
width: 320,
flex: 1
}
});
I'm facing same issue. What I observed is that WebView doesn't work if it's nested. If component returns just WebView, then everything is fine.
Using the answers from other users, I was able to get my react native with webview working both inside a view and outside a view. My problem came down to two things. Being on the android emulator and behind a proxy, I just had to go to my browser (chrome) in the android emulator and sign in to the corporate proxy. Secondly, some sites work and others will not work. Whether the webview was nested or not inside of a View tag, some sites like cnn.com and slack.com etc will work fine, but no matter what settings I tried for google.com it wouldn't work (even though the proxy will definitely allow google.com) Lastly, when I rebuild my application and push to the emulator the new app, sometimes it took an inordinately long time to load any site. But once the site was loaded, the links are quick and responsive. So if you don't at first see something after a build, also be patient. Hope this helps someone else.
My final app.js
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Dimensions
} from 'react-native';
import { WebView } from 'react-native';
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
type Props = {};
export default class App extends Component<Props> {
render() {
return (
<View style={{flex:1}}>
<WebView
style={styles.webview}
source={{uri: 'https://www.slack.com'}}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={false}
scalesPageToFit={true} />
</View>
);
}
}
const styles = StyleSheet.create({
webview: {
flex: 1,
backgroundColor: 'yellow',
width: deviceWidth,
height: deviceHeight
}
});
WebView works well on Android. However you need to enable javascript and dom storage for some web pages.
<WebView style={styles.webView}
source={{uri: 'https://google.com/'}}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
>
</WebView>
If you want the component to render the entire page, you need to wrap it with View that has flex: 1. The code below works for me:
<View style={{flex:1, alignItems: 'flex-end'}}>
<WebView
source={{uri: this.state.webContentLink}}
startInLoadingState={true}
scalesPageToFit={true} />
</View>
WebView is being moved to react-native-webview
.
None of the other answers worked except this method:
npm install --save react-native-webview
Then use it as follows:
<View style={{ flex: 1, alignItems: 'flex-end' }}>
<WebView
source={{
uri: 'https://www.yahoo.com',
}}
startInLoadingState={true}
scalesPageToFit={true}
style={{
width: 320,
height: 300,
}}
/>
</View>
<View>
<WebView
source={{uri: this.props.link}}
style={styles.webview}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
/>
</View>
and style as follows:
const React = require('react-native');
const { Dimensions } = React;
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
export default {
webview: {
width: deviceWidth,
height: deviceHeight
}
};
All this to deal with bad webview dimension, so just set a specific height and specific width too (deviceHeight and deviceWidth as the example above).
As of June 2020 (noting the date because React Native answers seem to become out-of-date quickly), the simplest solution to this appears to be:
import React from 'react'
import { View, StyleSheet } from 'react-native'
import { WebView } from 'react-native-webview'
export const ComponentWithWebView = () => {
return (
<View style={styles.view}>
<WebView source = {{uri: 'https://www.google.com/'}} />
</View>
)
}
const styles = StyleSheet.create({
view: {
alignSelf: 'stretch',
flex: 1,
}
}
This results in a WebView filling the available space and being nested within a View. I believe the typical problems faced when placing a WebView within a View is that View expects children to force the View to expand (that is, a Text component would take up some amount of width and height which the View then accommodates). WebView, on the other hand, expands to the size of the parent component unless a style is passed specifying the width. Therefore, a simple <View><WebView /></View> results in a 0 width and nothing shown on the screen. The earlier solutions of setting the WebView width work well but require either the device dimensions to be fetched (which might not be the desired width) or for the View to have an onLayout function AND have some way to expand the View to the desired space. I found it easiest to just apply the flex: 1 and alignSelf: 'stretch' for the View to fill the space as desired and then WebView to automatically follow suit.
Hope this helps someone before it becomes obsolete!
I ran into the same issue recently. And I found that
alignment: 'center'
was causing the issue for me. I commented it and the webView got loaded immediately.
I found the solution here :
https://github.com/facebook/react-native/issues/5974
'brunocvcunha's' response worked for me.
Let me give the simplest example which will work seamlessly:
import React from 'react';
import { WebView } from 'react-native';
export default class App extends React.Component {
render() {
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
/>
);
}
}
Do not add your WebView component within a view that created problem and webview url is not rendered rather styles of view will be shown.
I had the same issue and spent a day attempting to fix it. I copied in the UIExplorer webview example, and that didn't work.
I ultimately ended up upgrading react and creating a new react-native project and copying the files in there, and that fixed it.
I wish I had a better answer as to why that fixed it, but hopefully that helps
Below is piece of the code which worked for me.
render: function(){
return(
<View style={styles.container}>
<WebView url={'https://m.facebook.com'} style= {styles.webView}/>
</View>
);
}
I am doing React Native Webview, Could you please suggest me how to makeWebview loading the uri
render() {
return (
<Modal
animationType="slide"
ref={"webModal"}
style={{
justifyContent: 'center',
borderRadius: Platform.OS === 'ios' ? 30 : 0,
width: screen.width,
height: screen.height,borderColor:'red',
borderWidth: 5
}}
position='center'
backdrop={false}
onClosed={() => {
// alert("Modal closed");
}}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 20, top: 10 }} >
<Text style={{ fontSize: 24, fontWeight: '700' }}>
Interests
</Text>
<Icon name="ios-close" size={40} color='purple' onPress={() => { this.refs.webModal.close() }} />
</View>
<WebView
source={{ uri: this.state.link }}
style={{ marginTop: 20,borderColor:'green',
borderWidth: 5 }}
/>
</Modal>
);
}
}
import { WebView } from 'react-native'; is deprecated
use below line instead
npm install react-native-render-html#4.1.2 --save
then
import HTML from 'react-native-render-html';
react-native-render-html starting with version 4.2.0, react-native-webview is now a peer dependency. As a result, you need to install it yourself.
Try
<WebView
source={{ uri: "https://inhall.in/" }}
style={Styles.webView}
javaScriptEnabled={true}
scalesPageToFit />
javaScriptEnabled={true} might help