How to create reusable Modal in react native - react-native

I want to create a pop-up in react-native using Modal. Modal should be a created in such a way that it can be reused. Please let me know how to do this as I am new to react-native.

First you will need one state to control when the modal will show.
const [show, setShow] = useState(false)
And then when the condition was achieved, you will set this state to true and show the modal, I will let one example.
<TouchableOpacity
onPress={setShow(true)} />
//some icon
</TouchableOpacity>
Now you will use show to control your modal, but first let's create the modal component. You will create one js file and create the modal component inside it.
import React from 'react'
import {Modal, View, Text} from 'react-native'
const Modal = ({message, buttonMessage, show, setshow}) => {
return (
<Modal
animationType='slide'
transparent={true}
visible={show}
backgroundColor='white'
>
//What you want to show inside the modal, Views, Text, whatever, you will construct one 'screen' here
<View>
<Text>{message}</Text> //Showing the message
<Button
title={buttonMessage}
onPress={setShow(false)} //To not show the modal for example
/>
</View>
</Modal>
)}
export default Modal
Modal component are receiving at the start message and buttonMessage, so you can pass what you want to the component receive and then use it inside your code, and now when you invoke Modal you will pass message and buttonMessage as props to it use, you will see how. Note that Modal are being exported at the end, so now you can use import it in any screen that you want show it.
Let's suppose that you have one screen and will invoke the Modal component that you create.
import React, {useState} from 'react';
import { View, Text} from 'react-native';
import Modal from 'patch' //Note, patch will be where is the modal file that you create
const ContentCompenent = () => {
const [show, setShow] = useState(false)
return (
<View>
// Your screen content
// Your screen content
//Now you will invoke the Modal
<Modal message={'your message or your variable with the message'} buttomMessage={your message or your variable with the message} show={show} setShow={setShow} />
</View>
//When you setShow here to true, the modal will appears, and as you are passing setShow as prop to Modal, when you setShow(false) in the modal it will disappears.

Related

How to position an element on top of react native navigation bottom tabs

I'm using react native navigation bottom tabs, and I want to create a custom "bottom sheet" popup component, but I want that component to come over the bottom tabs. Does anybody know how to position elements on top of the bottom tabs?
Yes! You have to use react-native-portalize. Just wrap the elements you want to be rendered on top in a <Portal></Portal>. This will place it above a Bottom Tab navigator.
import { Portal } from 'react-native-portalize';
const FooterButton = () => {
return(
<Portal>
<View>
<Text>I appear above the Tab Navigator!</Text>
</View>
</Portal>
);
export default FooterButton;
Don't forget to wrap the whole app in the the Host:
//In app.js
import { Host } from 'react-native-portalize';
const App = () => {
return (
<Host>
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
</Host>
)
}
export default App;
NOTE: The elements inside the Portal, do not clear when the navigator navigates to another screen. So to get around this, you have to only display the Portal, when the screen is active. Thankfully React Navigation 5+ provides a useIsFocused hook that accomplishes this perfectly.
import { Portal } from 'react-native-portalize';
import { useIsFocused } from '#react-navigation/native';
const FooterButton = () => {
const isFocused = useIsFocused();
// Only display the button when screen is focused. Otherwise, it doesn't go away when you switch screens
return isFocused ? (
<Portal>
<View style={styles.buttonContainer}>
<View style={styles.footer}>{props.children}</View>
</View>
</Portal>
) : null;
};
export default FooterButton;
If you want a modal-style popup, you can wrap react-native-modalize and wrap it with react-native-modalize
Thanks to livin52 on Reddit for the solution

navigation does not work when imported - React native

When I use props.navigation.navigate("example"), it works normally. But if I import the component on another page it doesn't work anymore, props returns an empty object.
Works Fine:
const Menu = props =>{
console.log(props)
return(
<View style={styles.menuStyle}>
<TouchableOpacity style={styles.topicDiv} onPress={() =>props.navigation.navigate("Ads")}>
<View>
<Image style={styles.topicStyle} source={require ("../assets/security-camera.png")}/>
<Text style={styles.textStyle}>Câmeras</Text>
<Text style={styles.subTextStyle}>Veja como está a praia ao vivo 📷</Text>
If i try import Menu, navigation does not work:
import React from "react";
import { View } from "react-native";
import Menu from "./menu";
const Supermenu = () =>{
return(
<View>
<Menu></Menu>
</View>
)
}
export default Supermenu
If you use <Menu> inside of another component like <Supermenu>, React Navigation has no way to pass its navigation property in there. It only happens automatically if a component is a direct child of a screen (or its component property).
To have navigation available in Menu regardless of its position in the hierarchy, as long as it's a child of <NavigationContainer>, the best way is to make use of the useNavigation hook:
import { useNavigation } from '#react-navigation/core';
const Menu = props =>{
const navigation = useNavigation();
return (
<View style={styles.menuStyle}>
<TouchableOpacity style={styles.topicDiv} onPress={() => navigation.navigate("Ads")}>
...
See documentation for more detail.
If you are on an older version, there was also a HOC withNavigation that you could use.
You could also do the same in Supermenu and then pass navigation down manually.
use import {userNavigation} from '#react-navigation/core' instead of props navigate or you can add navigation props to the Menu component.

ReactNative Cannot update a component from inside the function body of a > different component

My HomeHeader component is like this:
import React from "react";
import { View, StyleSheet, Text, Image } from "react-native";
import Icon from "react-native-vector-icons/FontAwesome5";
export default function HomeHeader({ navigation }) {
return (
<View style={styles.home_header}>
<Icon
style={styles.menu}
name="bars"
size={30}
color="white"
onPress={navigation.toggleDrawer()}
/>
<Image
style={styles.header_logo}
source={require("../assets/logo.png")}
/>
<Text>Hello</Text>
</View>
);
}
And am using it in my Home screen like this:
return (
<View>
<HomeHeader navigation={navigation} />
</View>
)
But am receiving this error message:
Warning: Cannot update a component from inside the function body of a
different component.
What am trying to do is, I have separated out the header section of my HOME screen into a separate component called HomeHeader. And in this component, am attaching the event handler to toggle the opening/closing of the DrawerNavigation (left side drawer menu)
If I create a Button in my HOME screen and add the event handler to toggle the drawer, it works fine. But the issue happens only if I try this from inside my HomeHeader component.
Btw, am using ReactNavigation v5 and I even tried this method: https://reactnavigation.org/docs/connecting-navigation-prop/
No luck so far.
Change onPress={ navigation.toggleDrawer() } to onPress={ ()=> navigation.toggleDrawer() }
You can read more about this in here

How to implement RAM bundle and Inline Requires react native

I am using react native to build project and I am facing a problem with long launch time, I try to follow https://reactnative.dev/docs/ram-bundles-inline-requires, however it is not so clear about Investigating the Loaded Modules, and how to put only the necessary modules for first screen.
I am not also able to find index.(ios|android).js file (is it index.android.bundle).
If you can tell me how to extract only necessary modules and recommend docs or examples about implementing that?
With considering the official documents, pay attention to this example:
You have a Main screen (view) in your app like HomeScreen
In your HomeScreen, there are more and more components and logic in this page but assume we have a SettingsModal.
usually, modals will open when you touch a button.
Without inline require
you have to import your modal component to your HomeScreen at the top level of your module
with inline require
you will import your modal component to your HomeScreen when it needs to show!
Let's do this with code:
HomeScreen without inline require
import React, {useState} from 'react'
import {View, Text, Pressable} from 'react-native'
import SettingsModal from 'components/modal'
function HomeScreen() {
const [showModal, setShowModal] = useState(false)
const handleShowModal = () => setShowModal(prevState => !prevState)
return (
<View>
<Text> Home Screen </Text>
<Pressable onPress={handleShowModal}>
<Text> show settings </Text>
</Pressable >
{
showModal
? <SettingsModal />
: null
}
</View>
)
}
In the above example, we import SettingsModal in our HomeScreen top level with React and View and Text...
HomeScreen with inline require
import React, {useState} from 'react'
import {View, Text, Pressable} from 'react-native'
let SettingsModal = null;
function HomeScreen() {
const [showModal, setShowModal] = useState(false)
const handleShowModal = prevState => {
if (SettingsModal == null) {
SettingsModal = require('components/modal').SettingsModal
}
setShowModal(prevState => !prevState)
}
return (
<View>
<Text> Home Screen </Text>
<Pressable onPress={handleShowModal}>
<Text> show settings </Text>
</Pressable >
{
showModal
? <SettingsModal />
: null
}
</View>
)
}
In the above example, we check if SettingsModal has not been imported yet, then we will import this component to our HomeScreen file (after user touch the show settings button)

React Native Scrollview: scroll to top on button click

So I have a component with ScrollView which contains many elements, so you have to scroll a long way down.
Now there should be a button at the bottom of the page that on click will scroll the page back to top.
I already created the button as a FAB (floating action button) in an extra component.
It is integrated in a parent component, where the ScrollView is located.
What I found was that you have to create a ref in the ScrollView component and implement a button right there that uses this ref to make scrolling work. Simplified, here is what I have so far:
imports ...
const ParentComponent: React.FC<Props> = () => {
const scroll = React.createRef();
return (
<View>
<ScrollView ref={scroll}>
<SearchResult></SearchResult> // creates a very long list
<FloatingButton
onPress={() => scroll.current.scrollTo(0)}></FloatingButton>
</ScrollView>
</View>
);
};
export default ParentComponent;
As you can see, there is the component FloatingButton with the onPress() method.
Here is the implementation:
import React, {useState} from 'react';
import {Container, Content, Button, Icon, Fab} from 'native-base';
const FloatingButton: React.FC<Props> = () => {
return (
<Fab
position="bottomRight"
onPress={(???}>
<Icon name="arrow-round-up" />
</Fab>
);
};
export default FloatingButton;
Now the problem: Where should I do the onPress() method? Because if I leave it in the parent component, it won't work because it is not directly located in the Fab (in FloatingButton). I would like to do the onPress() logic in Fab, but if I do so, the ScrollView that it needs is not available, because it's in the parent component. My idea was to maybe passing the ref as prop into FloatingButton, but for some reason this didn't work.
Can someone please help me?
You could either let the parent hook into the FloatingButton's onPress function or pass the ref down to the FloatingButton directly.
export const Parent : FC<ParentProps> = props => {
const scrollRef = useRef<ScrollView>();
const onFabPress = () => {
scrollRef.current?.scrollTo({
y : 0,
animated : true
});
}
return (
<View>
<ScrollView ref={scrollRef}>
{/* Your content here */}
</ScrollView>
<FloatingButton onPress={onFabPress} />
</View>
);
}
export const FloatingButton : FC<FloatingButtonProps> = props => {
const { onPress } = props;
const onFabPress = () => {
// Do whatever logic you need to
// ...
onPress();
}
return (
<Fab position="bottomRight" onPress={onFabPress}>
<Icon name="arrow-round-up" />
</Fab>
);
}
You should determine the horizontal or vertical value you want to scroll to, like this code snippet.
onPress={()=>
this.scroll.current.scrollTo({ x:0, y:0 });
}
Please have a look at my snack code. Hope it might be helpful for you.
https://snack.expo.io/#anurodhs2/restless-edamame