Why is WebView in react native not opening? - reactjs

using #react-native-community/react-native-webview package (v^8.1.2) to open a webview in a RN v0.61.5 project, no matter what I do, I cannot get the webview to display once the button is pressed. I have a button that opens it, but nothing happens. none of the error functions from the props executed, nothing.
here's the setup:
<Components.Button
style={{ marginLeft: 15 }}
text={"It's Copied. Continue"}
type={'primary'}
onPress={() => (
<WebView
style={{ flex: 0, height: height, width: width }}
containerStyle={{ flex: 0, height: height, width: width }}
automaticallyAdjustContentInsets={true}
ref={(ref) => (this.webview = ref)}
source={{ uri: 'https://connect.stripe.com/oauth/authorize?response_type=code&client_id=<....>&scope=read_write' }}
originWhitelist={['https://*']}
renderError={(error) => <View style={{ flex: 1 }}><Text>{error}</Text></View>}
onError={syntheticEvent => {
const { nativeEvent } = syntheticEvent;
console.warn('WebView error: ', nativeEvent);
}}
onNavigatorStateChange={(event) => {
if (event.url !== this.props.stripeUri) {
this.webview.stopLoading();
Linking.openURL(event.url);
}
}}
/>
)}
/>
As you can see, the things ive tried:
setting flex:0 with a specified height, width
whitelisting uri with wildcard
setting various error props
re-running pod install
No errors register in console, no new error view renders.
the last time I looked at this code it was working fine, not sure what happened. Any thoughts?
EDIT: link to snack: https://snack.expo.io/uTkqnGbny

here is my snack code
https://snack.expo.io/sfDcMtiIR
Code:
import * as React from "react";
import {
Text,
View,
StyleSheet,
TouchableOpacity,
Linking,
Dimensions,
} from "react-native";
import { WebView } from "react-native-webview";
import Constants from "expo-constants";
const { height, width } = Dimensions.get("window");
const testURI = "https://google.com";
export default function App() {
const [isShowWebView, setIsShowWebView] = React.useState(false);
return (
<View style={styles.container}>
<TouchableOpacity
style={{
height: 50,
width: "100%",
borderRadius: 50,
justifyContent:"center",
alignItems:"center"
}}
onPress={() => setIsShowWebView(!isShowWebView)} >
<Text>Open Webview</Text>
</TouchableOpacity>
{isShowWebView && (
<WebView
style={{ height: height, width: width }}
containerStyle={{ height: height, width: width }}
ref={(ref) => (this.webview = ref)}
source={{ uri: testURI }}
renderError={(error) => (
<View style={{ flex: 1 }}>
<Text>{error}</Text>
</View>
)}
onError={(syntheticEvent) => {
const { nativeEvent } = syntheticEvent;
console.warn("WebView error: ", nativeEvent);
}}
onNavigatorStateChange={(event) => {
if (event.url !== testURI) {
this.webview.stopLoading();
Linking.openURL(event.url);
}
}}
/>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: "#ecf0f1",
padding: 8,
},
});

I think i know what you want.
I createfd a state var to we toggle the web view using the button.
Please try my snack (using Android or iOS).
https://snack.expo.io/lYItc9ACk
Code:
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity, Linking, Dimensions } from 'react-native';
import { WebView } from 'react-native-webview'
import Constants from 'expo-constants';
const {height, width} = Dimensions.get('window');
const testURI = "https://google.com";
export default function App() {
const [showWebView, setShowWebview] = React.useState(false);
return (
<View style={styles.container}>
<TouchableOpacity
style={{width:'90%', height: 50, backgroundColor:'#333', borderRadius: 50, alignSelf: 'center'}}
onPress={() => setShowWebview(!showWebView)}
>
</TouchableOpacity>
{ !!showWebView &&
<WebView
style={{ flex: 1, height: height, width: width }}
containerStyle={{ flex: 1, height: height, width: width }}
ref={(ref) => (this.webview = ref)}
source={{ uri: testURI }}
renderError={(error) => (
<View style={{ flex: 1 }}><Text>{error}</Text></View>
)}
onError={syntheticEvent => {
const { nativeEvent } = syntheticEvent;
console.warn('WebView error: ', nativeEvent);
}}
onNavigatorStateChange={(event) => {
if (event.url !== testURI) {
this.webview.stopLoading();
Linking.openURL(event.url);
}
}}
/>
}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

Remove the entire styling and just go with source: uri

Related

How to update screen dimensions in react native

I have been trying to update my screen dimensions in react native so that the component resizes on-screen rotation with no vain. I have created my style in a separate file (Styles.js) and imported the styles in my login page like below:
Styles.js
import {
StyleSheet,
Dimensions
} from "react-native";
import {
scale,
ScaledSheet
} from "react-native-size-matters";
const styles = ScaledSheet.create({
scrollViewContainer: {
backgroundColor: '#E20030',
alignItems: 'center',
height: Dimensions.get('window').height,
padding: '50#s'
},
container2: {
alignItems: 'center',
justifyContent: 'center',
width: Dimensions.get('window').width,
flex: 1,
},
loginRect: {
borderRadius: '30#s',
marginTop: '20#s',
width: Dimensions.get('window').width * 0.8,
backgroundColor: 'white',
alignItems: 'center'
},
SectionStyle: {
flexDirection: 'row',
marginTop: 0,
marginLeft: '35#s',
marginRight: '35#s',
borderWidth: '1#s',
borderRadius: '5#s',
borderColor: '#dadae8',
},
});
Login.js
import React, { } from 'react';
import {
Text, View, TextInput, TouchableOpacity,
KeyboardAvoidingView,
} from 'react-native';
import { mystyles, styles } from './Components/styles';
const LoginScreen = () => {
return (
<View style={mystyles.scrollViewContainer}>
<KeyboardAvoidingView behavior="padding" style={{ flex: 100 }}>
<View style={mystyles.scrollViewContainer}>
<View style={mystyles.loginRect}>
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1, marginLeft: 45, marginTop: 20 }}>
<Text style={{ color: 'black' }}>Username</Text>
</View>
</View>
<View style={styles.SectionStyle}>
<TextInput
style={styles.input}
/>
</View>
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1, marginLeft: 45, marginTop: 20 }}>
<Text style={{ color: 'black' }}>Password</Text>
</View>
</View>
<View style={styles.SectionStyle}>
<TextInput
style={styles.input}
/>
</View>
<TouchableOpacity>
<Text style={styles.buttonTextStyle}>LOGIN</Text>
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
</View>
)
}
export default LoginScreen;
So I have tried using Dimensions onchange listener in my Styles.js but I get an error
ERROR Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
I created this function in the Styles.js file
m
function getDimensions() {
const [dimensions, setDimensions] = useState({
window,
screen
});
useEffect(() => {
const subscription = Dimensions.addEventListener(
"change",
({
window,
screen
}) => {
setDimensions({
window,
screen
});
console.log(dimensions.window.height + " +++ " + dimensions.screen)
}
);
// return () => subscription?.remove();
});
return dimensions.window;
}
Is there any way I can update the component sizes once the screen has been rotated?
This is working for me to detect rotation or changes in the size of the screen (split mode in tablets for example) without eventListeners.
import { Dimensions } from "react-native";
...
useEffect(() => {
...
}, [Dimensions.get("screen").height, Dimensions.get("screen").width]);
Hope this help to anybody

react-native-pdf cannot set currentPage state to show up on display

i've done the react-native-pdf to show the slides of my pdf file. But, I want to set the current page state to show up on the display. And when the value is set, it'll refresh that screen and goes back to the first page automatically.
this is my code:
import React, { useState } from 'react';
import { StyleSheet, Dimensions, View, Text } from 'react-native';
import Pdf from 'react-native-pdf';
function Work() {
const [currentPage, setCurrentPage] = useState()
const ShowPdf = () => {
const source = { uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf', cache: true };
return (
<Pdf
source={source}
onLoadComplete={(numberOfPages, filePath) => {
console.log(`number of pages: ${numberOfPages}`);
}}
onPageChanged={(page, numberOfPages) => {
console.log(`current page: ${page}`);
setCurrentPage(page) //set the cuurentPage
}}
onError={(error) => {
console.log(error);
}}
onPressLink={(uri) => {
console.log(`Link presse: ${uri}`)
}}
style={styles.pdf} />
)
}
return (
<View style={styles.container}>
<ShowPdf />
<View style={styles.pageNumber}>
<Text>{currentPage}</Text>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
//marginTop: 25,
//backgroundColor: 'red',
backfaceVisibility: 'hidden'
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
pageNumber: {
position: 'absolute',
left: 20,
top: 20,
backgroundColor: 'rgba(173, 173, 173, 0.5)',
padding: 13,
borderRadius: 6,
}
});
export default Work;
my emulator display:
image
Anyway I can fix this?
Instead of use this
<View style={styles.container}>
<ShowPdf />
<View style={styles.pageNumber}>
<Text>{currentPage}</Text>
</View>
</View>
please use it
<View style={styles.container}>
<Pdf
source={{ uri: path }}
onLoadComplete={(numberOfPages, filePath) => {
console.log(`number of pages: ${numberOfPages}`);
}}
onPageChanged={(page, numberOfPages) => {
console.log(`current page: ${page}`);
setCurrentPage(page) //set the cuurentPage
}}
onError={(error) => {
console.log(error);
}}
onPressLink={(uri) => {
console.log(`Link presse: ${uri}`)
}}
style={styles.pdf} />
<View style={styles.pageNumber}>
<Text>{currentPage}</Text>
</View>
</View>
<ShowPdf/> is your custom react component it will be re-rendered for every page change. So, that is why you faced this problem

CustomDrawerNavigator: Change Active and Inactive Background Colour

On react-navigation/drawer's DrawerItem, is there a way to add active and inactive background colour? I followed this document to implement this https://reactnavigation.org/docs/drawer-navigator/.
I have added theses code lines to the drawerItems. But it won't work for me.
drawerContentOptions={{
activeTintColor: '#fff', /* font color for active screen label */
activeBackgroundColor: '#68f', /* bg color for active screen */
inactiveTintColor: 'grey', /* Font color for inactive screens' labels */
}}
initialized by the following,
import * as React from 'react';
import {
Button,
View,
Text,
StyleSheet,
TouchableOpacity,
Image,
} from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
} from '#react-navigation/drawer';
import Home from '../home/containers';
import NavigationService from '../../navigation/NavigationService';
import * as homeActions from '../../features/home/actions';
import * as loginActions from '../../features/login/actions';
import { Images } from '../../config';
import i18n from 'i18n-js';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => NavigationService.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => NavigationService.goBack()} title="Go back home" />
</View>
);
}
function CustomDrawerContent({ props, navigation }) {
const dispatch = useDispatch();
const outlets = useSelector((state) => state.homeReducer.outlets);
const defaultOutLet = useSelector((state) => state.homeReducer.defaultOutLet);
const drawerItems = outlets.map((outlet) => {
return (
console.log("############## nav drawr ################## " + outlet.name),
<DrawerItem
{...props}
key={outlet.userCompanyId}
label={outlet.name}
onPress={() => {
dispatch(homeActions.changeSelectedOutlet(outlet));
navigation.closeDrawer();
}}
/>
);
});
return (
<View style={styles.flexView}>
<View style={styles.container}>
<Image
style={styles.image}
source={Images.icons.logo}
resizeMode="contain"
/>
{defaultOutLet && <Text style={styles.text}>{defaultOutLet.name}</Text>}
</View>
<View style={styles.separator} />
<View style={styles.flexView}>{drawerItems}</View>
<View style={styles.separator} />
<View style={styles.bottomView}>
<TouchableOpacity
style={styles.logoutContainer}
onPress={() => {
dispatch(homeActions.clearUserCompany());
dispatch(loginActions.completeLogOutClearingUserData());
}}>
<Image
style={styles.logoutIcon}
source={Images.icons.power}
resizeMode="center"
/>
<Text style={styles.logoutText}>{i18n.t('common.logout')}</Text>
</TouchableOpacity>
</View>
</View>
);
}
const Drawer = createDrawerNavigator();
export default function DrawerNavigator() {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}
initialRouteName="Home">
<Drawer.Screen name="Home" component={Home} />
</Drawer.Navigator>
);
}
const styles = StyleSheet.create({
container: {
flex: 0.3,
width: '100%',
backgroundColor: 'white',
},
flexView: {
flex: 1,
},
text: {
marginVertical: 12,
color: 'black',
textAlign: 'center',
},
logoutContainer: {
flexDirection: 'row',
alignItems: 'center',
width: '100%',
},
logoutText: {
color: 'gray',
},
logoutIcon: {
flex: 0.4,
},
image: {
flex: 1,
marginTop: 20,
alignSelf: 'center',
},
separator: {
width: '100%',
height: 1,
backgroundColor: 'gray',
},
bottomView: {
flex: 0.15,
width: '100%',
justifyContent: 'center',
},
});

Make the Header scroll down with FlatList and Animated - React Native

I didn't find any soulotion to do animated with FlatList,
I want to hide my Header when I scroll down like In Facebook app.
I tried To use FlatList with diffClamp() without success,
I don't know if I can do it with FlatList but I need also LazyLoading,
Someone Can help me?
This is my Header:
import React, { useState } from "react";
import {
View,
Animated,
Text,
Dimensions,
TouchableOpacity
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Ionicons } from "#expo/vector-icons";
const Header = props => {
const params = props.scene.route.params;
const [headerHeight] = useState(
params !== undefined && params.changingHeight !== undefined
? params.changingHeight
: Dimensions.get("window").height * 0.065
);
return (
<SafeAreaView style={{ backgroundColor: "rgb(152,53,349)" }}>
<Animated.View
style={{
width: Dimensions.get("window").width,
height: headerHeight,
flexDirection: "row",
backgroundColor: "rgb(152,53,349)"
}}
>
<TouchableOpacity
onPress={() => {
props.navigation.openDrawer();
}}
>
<View
style={{
paddingVertical: "15%",
justifyContent: "center",
paddingHorizontal: 25
}}
>
<Ionicons name="ios-menu" size={30} color={"white"} />
</View>
</TouchableOpacity>
<View style={{ justifyContent: "center", marginLeft: "23%" }}>
<Text
style={{
fontSize: 20,
fontWeight: "bold",
textAlign: "center",
color: "white"
}}
>
MyGameenter code here{" "}
</Text>
</View>
</Animated.View>
</SafeAreaView>
);
};
export default Header;
This is my FlatLIst:
import React from "react";
import { View, FlatList, StyleSheet } from "react-native";
import { EVENTS } from "../data/dummy-data";
import Event from "./Event";
const renderGridItem = itemData => {
return <Event item={itemData.item} />;
};
const ShowEvents = props => {
return (
<View style={styles.list}>
<FlatList
keyExtractor={(item, index) => item.id}
data={EVENTS}
renderItem={renderGridItem}
numColumns={1}
/>
</View>
);
};
const styles = StyleSheet.create({
list: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
export default ShowEvents;
Use
onScroll={(e) => console.log(e.nativeEvent.contentOffset.y)}
Working Example: https://snack.expo.io/#msbot01/privileged-candies
import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, FlatList } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
DATA: [],
previous: 0,
hide: false,
};
}
componentDidMount() {
var array = [];
for (var i = 0; i < 100; i++) {
var a = { id: i, value: i };
array.push(a);
}
this.setData(array);
}
setData(a) {
this.setState({
DATA: a,
});
}
Item({ title }) {
return (
<View
style={{
width: '100%',
height: 30,
marginTop: 5,
backgroundColor: 'green',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text />
</View>
);
}
_onScroll(event) {
// console.log('>>>>>>>>>>>'+this.state.data);
if (this.state.previous < event) {
this.setState({
hide: true,
previous: event,
});
} else {
this.setState({
hide: false,
previous: event,
});
}
console.log(event);
}
render() {
return (
<View style={{ flex: 1 }}>
{this.state.hide == true ? null : (
<View
style={{
width: '100%',
height: 50,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>Hide me while scrolling</Text>
</View>
)}
<FlatList
onScroll={e => this._onScroll(e.nativeEvent.contentOffset.y)}
data={this.state.DATA}
renderItem={({ item }) => (
<View
style={{
width: '100%',
height: 30,
marginTop: 5,
backgroundColor: 'green',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text />
</View>
)}
keyExtractor={item => item.id}
/>
</View>
);
}
}
const styles = StyleSheet.create({});
import React, { useState } from "react";
import { View, FlatList, StyleSheet, Platform, Dimensions } from "react-native";
import { EVENTS } from "../data/dummy-data";
import Event from "./Event";
const HeaderHeight = () => {
if (Platform.OS === "android" && Dimensions.get("window").height < 600)
return Dimensions.get("window").height * 0.075 + 20;
else if (Platform.OS === "android")
return Dimensions.get("window").height * 0.058 + 20;
else return Dimensions.get("window").height * 0.01 + 20;
};
const renderGridItem = itemData => {
return <Event item={itemData.item} />;
};
const ShowEvents = props => {
const [previous, SetPrevious] = useState(false);
const [hide, SetHide] = useState(false);
_onScroll = event => {
const headerHeight = HeaderHeight();
if (event > headerHeight) {
SetHide(true);
props.navigation.setParams({
hide: true
});
SetPrevious(event);
} else if (event < 0.1) {
SetHide(false);
props.navigation.setParams({
hide: false
});
SetPrevious(event);
}
};
return (
<View style={styles.list}>
<FlatList
onScroll={e => _onScroll(e.nativeEvent.contentOffset.y)}
keyExtractor={(item, index) => item.id}
data={EVENTS}
renderItem={renderGridItem}
numColumns={1}
/>
</View>
);
};
const styles = StyleSheet.create({
list: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
export default ShowEvents;

react native scrollview showing up on down part of the emulator

I am trying to create a scroll view in react native.
I gave full-device-width and height for the scroll-view.
width is working but height is not working so the app is showing only on down part of the emulator,
I would like to know how can I make this showing up in fullscreen and also why this error occurring.
this is how it's loading on emulator.
you can find my react-native code below
import React, { Component } from 'react';
// import Counterpart from './Counterpart'
import contacts from './contacts'
import {
View,
Button,
ScrollView,
Switch,
Text,
Input,
StyleSheet,
Dimensions,
} from 'react-native';
const widthfull = Dimensions.get('window').width; //full width
const heightfull = Dimensions.get('window').height; //full height
const styles = StyleSheet.create({
mainwrap: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
zIndex:1,
},
countfont: {
fontSize: 120,
},
marginfromtop: {
display: 'flex',
flex: 1,
paddingTop: 50,
},
ScrollViewstles: {
display: 'flex',
flex: 1,
margin:0,
padding:0,
zIndex:2,
width:widthfull,
height:heightfull,
paddingLeft:30
}
});
export default class App extends Component {
state = {
showCounter: true
}
toggglecounter = () => {
this.setState(() => ({showCounter: !this.state.showCounter}))
}
render() {
if (this.state.showCounter) {
return (
<View style={styles.mainwrap}>
<View style={[styles.marginfromtop, styles.countfont]}>
<Button
style={{ marginTop: 50 }}
onPress={this.toggglecounter}
title="Toggle Contacts"
/>
</View>
<View style={styles.mainwrap}>
<ScrollView style={styles.ScrollViewstles}>
{contacts.map(c => (
<Text key={c.key}>{c.name}</Text>
))}
</ScrollView>
</View>
</View>
);
} else {
return (
<View style={[styles.marginfromtop, styles.countfont]}>
<Button
style={{ marginTop: 50 }}
onPress={this.toggglecounter}
title="Toggle Contacts"
/>
</View>
);
}
}
}
remove flex: 1 from marginfromtop
marginfromtop: {
paddingTop: 50,
},

Resources