Best practice for using react-native modals - react-native

My react-native app has several situations where different modals can be presented. I am wondering what's the best way to accomplish this. In general I see two different approaches:
a)
On the root view I always have the Modal-component mounted and simply switch the content, like this...
<View>
{...}
<Modal visible={this.props.modal > 0}>
{this.props.modal === 1 && <ModalContent1 />}
{this.props.modal === 2 && <ModalContent2 />}
{this.props.modal === 3 && <ModalContent3 />}
</Modal>
</View>
b) Every modal brings it's own Modal-component and is mounted somewhere in the tree, near the place it is triggered from.
Which way would you prefer and why?
A question that applies to both approaches is, if the Modal-component should always be mounted and only triggered using the visible-prop. If that's the way to go, I assume approach b) needs more memory, because multiple instances of the Modal-component are created.

I personally use the Stack Navigator from React Navigation to implement modals within my application. My modals include a "create post modal", "no internet connection modal" among others.
This allows me to access these modals from anywhere in my application and can persist/block other actions directly. To learn more about how to use React Navigation, you can read up on these two links:
To understand the StackNavigator, it has a section specifically for transparent background modals
To learn more about implementing modals in React Navigation in general.

Related

Is there any way to pass state other than context or props?

https://reactjs.org/docs/context.html states:
Context is primarily used when some data needs to be accessible by many components at different nesting levels. Apply it sparingly because it makes component reuse more difficult.
https://reactnavigation.org/docs/hello-react-navigation states:
Note: By default, React Navigation applies optimizations to screen components to prevent unnecessary renders. Using a render callback removes those optimizations. So if you use a render callback, you'll need to ensure that you use React.memo or React.PureComponent for your screen components to avoid performance issues.
and also states:
Use React context and wrap the navigator with a context provider to pass data to the screens (recommended).
Use a render callback for the screen instead of specifying a component prop:
This implies in React Navigation, for performance, you really want context which destroys the re-usability. Is there a 3rd way (e.g. recoiljs or any other things that may have come about)? I am hoping to possibly get the best of both somehow.
if i'm getting you right you want to pass props to another component without props drilling.
what i would suggest is to use the navigation hook navigate/push methods like this -
const navigation = useNavigation()
onPress={() => navigation.push('ScreenName',{'item': item})}
onPress={() => navigation.navigate('ScreenName',{'item': item})}
when item is the prop, and in the other screen you could accsess it using
route.params.item

How can i open another Screen using a button ReactNative

Let me explain properly what I want to do.
I have these screens in react-native mobile-app
App.js
WalletDetails.js
Then I have another screen called PaymentDetails.js amongst many other screens
So what I want to do is that I need a button with onPress that would open directly walletDetails.js screen from PaymentDetails.js.
I have this code already on the paymentdetails page
<TouchableOpacity style={styles.cardPayBtn} onPress={()=>props.navigation.navigate("WalletDetails"); }}> <Text style={styles.buttonTitle}>{userdata && userdata.usertype == 'rider' ? t('payWithCard') : t('request_payment')}</Text> </TouchableOpacity>
I think for navigating between screens, React recomments react-navigation, it's a module to handle multiple screens (I'm using it myself and I really like it).
To get started, the react-navigation getting-started-guide helps a lot!
You can use for this navigation purpose between one screen to another.
onPress={()=>this.props.navigation.navigate("WalletDetails")

Custom List View is taking too much time on page load react native

I need some help. I've made a custom list view with some animation (drag and drop). everything is working fine except when there is large number of data, its taking too much time to load the page/when navigating back from another page. Is there any technique where I can reduce the page loading time? Please do not suggest any external packages, and also I cannot use flatlist either, due to my Animated.Scrollview conflicting with Flatlist own Scrollview. I've searched online, and everyone is using flatlist, which i cannot use. Or is it possible to ignore FlatList Own ScrollView?
Found an alternate solution here. You can use FlatList for larger data. Then pass your Animated.ScrollView component as a props through FlatList.
renderScrollComponent={(props) => (
<Animated.ScrollView
{...props}
onScroll={(event) => {
onScroll({ y: feedScroll })(event)
props.onScroll(event)
}}
/>
)}

React Native Navigation Updating Data

I am building an app where I am using Redux and the React-Navigation library. I have a list of workouts in a FlatList:
<FlatList
style={{ backgroundColor: colors.background }}
data={this.props.workoutsList}
renderItem={({ item }) =>
<ListItem workout={item} onPress={() => this.props.navigation.navigate('Workout', item)} />
}
keyExtractor={(item) => item.id}
/>
This shows my list properly, and I can navigate to the specific Workout page for each row I click on, and am provided the attached workout on each click. On this specific workout page, I have an Edit Workout form where users can, for example, update the name and time of the workout.
All of this is no problem...the issue I have comes when I press the back button on the menu that takes me back to the main list of all workouts. The FlatList is still showing the old data and is a source of my problem. It is caching this data so my new saves are not being shown, and as a consequence when I click on the list item again, it attaches the old workout information rather than the newest one I just saved. (hope that makes sense)
I have seen a somewhat similar question: React Navigation: How to update navigation title for parent, when value comes from redux and gets updated in child? but it does not quite encapsulate my main question:
Is it possible where a FlatList can update a specific row from a redux setup, while also maintaining it's scroll position?
I see this working extremely nicely on the Facebook app....as someone is scrolling down their Wall, let's say they click on the item saying "xx Comments". This will navigate the app to a page showing only this post. You can Like/Comment and when you press the back arrow, you are brought back exactly in the scroll position of the Wall you were before AND the number of likes/comments has been update to show your contribution. Is this possible in React Native?
If this is not possible...does anybody know how to at least refresh a page when navigating from a back button in React-Navigation?
EDIT I am open to using another navigation library if there is a better setup somewhere else!
UPDATE
I have attempted several ways to solve this problem, one way I tried was this:
When I made a successful save of the form, I dispatched an action of 'NEEDS_REFRESHING'. This set a redux prop that I picked up on the main FlatList page. In the render of that page, I had an:
if (this.props.needsRefreshing) {
console.log('Needs Refreshing');
this.props.getWorkouts();
}
I was seeing the console, and my FlatList page was properly refreshing (it wasn't bringing me back to the correct scroll position as it just refreshed the main list). but I always got a warning from React Native saying:
Cannot update during an existing state transition (such as within
`render` or another component's constructor). Render methods should be
a pure function of props and state; constructor side-effects are an
anti-pattern, but can be moved to `componentWillMount`.
When I moved this to componentWillMount, the proper refreshing changes were then never getting called and even a console.log in componentWillMount would not show up.
Have you try scrollToIndex(params: object) method? https://facebook.github.io/react-native/docs/flatlist.html#scrolltoindex
And also if you want to update your data inside flatList you should add extraData in Props
https://facebook.github.io/react-native/docs/flatlist.html#extradata
If you use react-navigation goBack() to a screen, that screen will never trigger componentWillMount because this screen never unmount, so please use redux instead.

how to show the hidden navbar in react native

i am troubling using of NavigatorIOS in react native,
<NavigatorIOS
style={styles.navigator}
initialRoute={{
title:'xxx',
component:xxx
}}
navigationBarHidden={true} />
here component xxx is my starting file here i don’t want navigator,after this i am using login screen there also i don’t want navigator after completion of the these screens,I need a navigator in my screen.
for hiding i used above code but to show it in child screen i wrote like this but not showing
this.props.navigator.push({
component:xxxx
title:’xxxx’,
navigationBarHidden:false
})
any help much appreciated
There are a lot of issues when using NavigatorIos. You have 2 options:
Dump NavigatorIos and move to Navigator. I was in the same scenario as you. I was using NavigatorIos and I wanted to completely replace the scene. It was a known issue and since Facebook stopped developing it and moved completely to Navigator, I was pretty much forced to make the change.
Here is more info: Navigator comparison
You can use a custom navigator like this one by Kureev. However, you should take into consideration that the way he implemented it, the navigator bar is part of your view, so when you move to a new scene, the whole page shifts, including your navigator.
I tried both option #1 and #2, and ultimately went with #1 and never looked back. It feels much more native and there is growing support for it.
Hope that helps.