I'm new to React Native and I have a simple app which opens a Webview when a button is pressed. If the navigation state changes, I want to close the Webview. I'm able to know when to close it but unable to find how.
The doc does not mention any function to do it. What's the solution for this?
version : react-native: 0.47.2
you can add it in Modal
_onNavigationStateChange (webViewState) {
this.hide()
}
show () {
this.setState({ modalVisible: true })
}
hide () {
this.setState({ modalVisible: false })
}
render () {
const { clientId, redirectUrl, scopes } = this.props
return (
<Modal
animationType={'slide'}
visible={this.state.modalVisible}
onRequestClose={this.hide.bind(this)}
transparent
>
<View style={styles.modalWarp}>
<View style={styles.contentWarp}>
<WebView
style={[{ flex: 1 }, this.props.styles]}
source={{ uri: `http://google.com` }}
scalesPageToFit
startInLoadingState
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
onError={this._onNavigationStateChange.bind(this)}
/>
<TouchableOpacity onPress={this.hide.bind(this)} style={styles.btnStyle}>
<Text style={styles.closeStyle}>close</Text>
</TouchableOpacity>
</View>
</View>
</Modal >
)
}
for anyone who wants a custom close button or such, you could also do like this.
<SafeAreaView style={{ flex: 1 }}>
<TouchableOpacity onPress={closeWebView}>
<Text>x</Text>
</TouchableOpacity>
<WebView style={{ flex: 1 }} source={{ uri }} />
</SafeAreaView>
Related
As title says, I need to create a modal popup for every list item for the selected sizes to be displayed. I'm using the react-native-popup-dialog but without results. Could you help me? Here's my code:
step1 = () => {
return (
<View style={{ flex: 8}}>
<Text h3 style={{ ...styles.title, marginVertical: 10.0 }}>{this.state.user=="User"?"Size":"CargoSize"}</Text>
<ScrollView>
<View style={{ marginHorizontal: 16.0 }}>{
this.state.size.map((l, i) => (
<ListItem key={i} onPress={() => this.setState({sizeSelected: i, sizeName: l.title, sizeId: l.id})} underlayColor='transparent'
containerStyle={{backgroundColor: this.state.sizeSelected==i?'#F76858':'white', borderWidth: 1.0,
borderColor: '#707070', marginBottom: 10.0, paddingVertical: 5.0, paddingHorizontal: 40.0}}>
<ListItem.Content>
<View style={{
flexDirection: 'row', alignItems: 'center',
justifyContent: 'center'
}}>
<Text style={styles.textSize}>{l.title}</Text>
<Text style={{ fontSize: 16 }}>{l.example}</Text>
</View>
</ListItem.Content>
</ListItem>
))
}</View>
</ScrollView>
</View>
);
}
I believe you can declare a single modal in your list component and show or hide the modal when the user presses the listItem. Also, make the pressed item active and pass the item to your modal so that the modal can show the details of the active item.
App.js
export default function App() {
const [modalVisible, setModalVisible] = React.useState(false);
const [activeItem, setActiveItem] = React.useState(null);
const onPress = (item) => {
setActiveItem(item)
setModalVisible(true)
}
const renderItem = ({ item }) => (
<TouchableOpacity onPress={()=>onPress(item)}>
<Item title={item.title} />
</TouchableOpacity>
);
return (
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
<Popup modalVisible={modalVisible} setModalVisible={setModalVisible} activeItem={activeItem} />
</View>
);
}
Modal.js
export default function Popup({modalVisible, setModalVisible, activeItem}) {
return (
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>{activeItem?.title}</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: '#2196F3' }}
onPress={() => {
setModalVisible(!modalVisible);
}}>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
}
Here is a working demo for you.
I made something similar in my react-native project and do this:
Made with {useState} the variables i need in my modal, example, the name of my component
Wrap the ListItem component in a Pressable component
Put the onPress={() => {//Put your code here}} function, inside you will put the SetVariable of the variable you want in the modal
The Pressable will update the variable with the wich you want in the modal
I am working on a simple React Native e-commerce app and i ran into a issue. I am trying to add the option to change the language, and it has worked so far with the Redux but now i need to dynamically change the sidebar menu and I cant because it is hardcoded as a prop.The code for the menu is this.
const ShopNavigator = createDrawerNavigator(
{
Produktetee: ProductsNavigator,
Rezervimet: OrdersNavigator,
Postoni: AdminNavigator},
{
contentOptions: {
activeTintColor: MyColors.primary
},
contentComponent: props => {
const {log_out} = useSelector(state => state.language)
const dispatch = useDispatch();
return (
<View style={{ flex: 1, paddingTop: 50 }}>
<SafeAreaView forceInset={{ top: "always", horizontal: "never" }}>
<DrawerItems {...props} />
<Button
title={log_out}
color={MyColors.primary}
onPress={() => {
dispatch(authActions.logOut());
// props.navigation.navigate("Auth");
}}
/>
<View style={{flexDirection: 'row'}}>
<View style={{flex:1 , marginRight:10, marginTop: 5,}} >
<Button
title="English"
type="outline"
color={MyColors.primary}
onPress={()=>{
dispatch(index.selectLanguage(languages.english))
}}
/>
</View>
<View style={{flex:1, marginTop: 5,}} >
<Button
title="Shqip"
type="outline"
color={MyColors.primary}
onPress={()=>{
dispatch(index.selectLanguage(languages.albanian))
}}
/>
</View>
</View>
</SafeAreaView>
</View>
);
}
}
);
I am trying to use the hook, but I can't. If somebody could help me I would be very grateful.
I have made a Home page in which there are three buttons in the header (like a tab navigator) I want something like on clicking each button a screen appears beneath the header, as shown in the image below:
Here's what I have tried:
constructor(props) {
super(props);
this.state = {
initialstate: 0, //Setting initial state for screens
};
}
render(){
return(
<View style={styles.container}>
<TouchableOpacity onPress={() => this.setState({ initialstate: 0})}>
<Image source={require('../../assets/add.png')}
resizeMode="contain"/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 1})}>
<Image source={require('../../assets/request.png')}
resizeMode="contain"/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.setState({ cardstate: 2})}>
<Image source={require('../../assets/send.png')}
resizeMode="contain"/>
</TouchableOpacity>
{this.state.initialstate == 0 ? ( <RequestComp/> ) : ( <TopUpComp/> ) }
//Over Here when I use the Third Screen like " : <SendComp/> " it gives me JSX error says "EXPECTED }"
</View>
Ciao, what you need seems more like a popup that appears from the bottom of the screen. I use react-native-popup-ui Toast component to do that.
Something like:
import { Root, Toast } from 'popup-ui'
...
<Root>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
onPress={() =>
Toast.show({
title: 'User created',
text: 'Your user was successfully created, use the app now.',
color: '#2ecc71'
})
}
>
<Text>Call Toast</Text>
</TouchableOpacity>
</View>
</Root>
And the result is:
Note: I have android and the Taost is overlapped by android navigation bar but on iOS you should see all the Toast component
you are using a ternary operator ( initial ? true : false ) which can work only for two components in your case.
i just wanted to give pull to referesh access in my react native webveiew app .
and i used a library called react-native-pull-to-refresh and used the tag and there i got my ui changed .
the webview was shifted down and top half was occupied by the tag
here is the code
render() {
return (
<View style={styles.container}>
<PTRView style={{}} onRefresh={()=>{this.Gymkhana.reload()}} />
<WebView
source={{ uri: "http://www.gymkhana.iitkgp.ac.in/index.php" }}
domStorageEnabled={true}
startInLoadingState={true}
renderLoading={this.ActivityIndicatorLoadingView}
ref={ref => (this.Gymkhana = ref)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center"
},
});
please resolve my error
The problem might be cause by the fact you are using it incorectly, you should wrap your content in the PTRView and not just use it as separate element. refer to doc: https://www.npmjs.com/package/react-native-pull-to-refresh
render() {
return (
<View style={styles.container}>
<PTRView style={{}} onRefresh={()=>{this.Gymkhana.reload()}} >
<WebView
source={{ uri: "http://www.gymkhana.iitkgp.ac.in/index.php" }}
domStorageEnabled={true}
startInLoadingState={true}
renderLoading={this.ActivityIndicatorLoadingView}
ref={ref => (this.Gymkhana = ref)}
/>
</PTRView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center"
},
});
I'm still learning ReactJS / React Native and I'm stuck with a stupid thing I'm sure. Here's my case: I want to receive data in my child component and display it in a Modal. So:
I have a function like this (axios, API, ...):
getProductInfo = (product_id) => {
axios.get(
`API-EXAMPLE`
)
.then((response) => {
this.setState({
isVisible: false,
productInfo: response.data
})
console.log(this.state.productInfo);
})
}
I pass the function to my Child Component with the "onModalPress":
<CatalogList productsList={this.state.displayProducts} onModalPress={this.getProductInfo}/>
And here, some info about the Child Component:
const CatalogList = ({productsList, onModalPress}) => (
<Card containerStyle={styles.container}>
<View style={{ padding:20, margin:0, flexDirection: 'row', flexWrap: 'wrap', flex: 1, justifyContent: 'space-between' }}>
{
productsList.map((p, i) => {
return (
<TouchableHighlight key={i} onPress={() => onModalPress(p.id)}>
<View style={style.card}>
<View style={style.content}>
<View style={{width: 170, zIndex: 2}}>
<Text style={style.name}>{p.id}</Text>
<Text style={style.name}>{p.name}</Text>
<Text style={style.winemaker}>Domaine : {p.domain}</Text>
<Text style={style.winemaker}>Origine : {p.wine_origin}</Text>
<Text style={style.aop}>Appellation : {p.appellation}</Text>
</View>
<Image
style={style.image}
source={{ uri: p.image, width: 140, height: 225, }}
/>
</View>
<View style={style.entitled}>
<Text style={[style.priceText, style.cadetGrey]}>{p.publicPriceText}</Text>
<Text style={style.priceText}>{p.subscriberPriceText}</Text>
</View>
<View style={style.row}>
<Text style={[style.price, style.cadetGrey]}>{p.price} €</Text>
<Text style={style.price}>{p.subscriber_price} €</Text>
</View>
<View style={[{backgroundColor: p.label_colour}, style.label]}>
<Text style={style.labelText}>{p.label}</Text>
</View>
<Modal isVisible={false}>
<View style={{ flex: 1 }}>
{/* <Text>{productInfo.rewiew_wine_waiter}</Text> */}
</View>
</Modal>
</View>
</TouchableHighlight>
);
})
}
</View>
</Card>
);
The "p.id" comes from another data (productList) that I get with another Axios API Call. With "p.id" I get the product_id I need in my function
getProductInfo
Everything works and I display the info inside my console.log (this.state.productInfo).
My issue and I think is easy... It's how can I "store/stock" this info I have in the console.log in a const/props to use it in my Modal and call it like in this example:
<Modal isVisible={false}>
<View style={{ flex: 1 }}>
<Text>{productInfo.rewiew_wine_waiter}</Text>
</View>
</Modal>
Of course, any other advice is welcome!
React is all about one-way data flow down the component hierarchy
Let's assume that you have a Container component that fetch all the data:
class MyContainer extends Component{
state = {
myItensToDisplay: []
}
componentDidMount(){
//axios request
.then(res => this.setState({myItensToDisplay: res.itens}))
}
}
Looking good! Now you have all the data you want to display fetched and stored in your container's state. Let's pass it to a Itemcomponent:
class MyContainer extends Component{
// All the code from above
render(){
const itens = this.state.myDataToDisplay.map( item =>{
return(<Item name={item.name} price={item.price} />);
})
return(
<div>
{itens}
</div>
)
}
}
Now you are fetching all the data you want to display in a parent component and distributing that data to it's childrens via props.