From f2eda6ce48a38fa5509360cee4184eef3e48cf84 Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Sun, 28 Oct 2018 17:29:28 -0700 Subject: [PATCH] Use react-native-screens and keep inactive screens in memory, like with tabs --- packages/drawer/src/views/DrawerView.js | 72 ++++++++++++++++--- .../drawer/src/views/ResourceSavingScene.js | 57 +++++++++++++++ 2 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 packages/drawer/src/views/ResourceSavingScene.js diff --git a/packages/drawer/src/views/DrawerView.js b/packages/drawer/src/views/DrawerView.js index 843638ee..ec86cd0d 100644 --- a/packages/drawer/src/views/DrawerView.js +++ b/packages/drawer/src/views/DrawerView.js @@ -1,16 +1,36 @@ import React from 'react'; -import { Dimensions } from 'react-native'; +import { Dimensions, StyleSheet } from 'react-native'; import { SceneView } from '@react-navigation/core'; +// eslint-disable-next-line import/no-unresolved +import { ScreenContainer } from 'react-native-screens'; + import DrawerActions from '../routers/DrawerActions'; import DrawerLayout from './DrawerLayout'; import DrawerSidebar from './DrawerSidebar'; import DrawerGestureContext from '../utils/DrawerGestureContext'; +import ResourceSavingScene from '../views/ResourceSavingScene'; /** * Component that renders the drawer. */ export default class DrawerView extends React.PureComponent { + static defaultProps = { + lazy: true, + }; + + static getDerivedStateFromProps(nextProps, prevState) { + const { index } = nextProps.navigation.state; + + return { + // Set the current tab to be loaded if it was not loaded before + loaded: prevState.loaded.includes(index) + ? prevState.loaded + : [...prevState.loaded, index], + }; + } + state = { + loaded: [this.props.navigation.state.index], drawerWidth: typeof this.props.navigationConfig.drawerWidth === 'function' ? this.props.navigationConfig.drawerWidth() @@ -121,11 +141,12 @@ export default class DrawerView extends React.PureComponent { }; render() { - const { state } = this.props.navigation; - const activeKey = state.routes[state.index].key; - const descriptor = this.props.descriptors[activeKey]; - - const { drawerLockMode } = descriptor.options; + const { lazy, navigation } = this.props; + const { loaded } = this.state; + const { state } = navigation; + const { routes } = state; + const activeKey = routes[state.index].key; + const { drawerLockMode } = this.props.descriptors[activeKey].options; return ( - + + {routes.map((route, index) => { + if (lazy && !loaded.includes(index)) { + // Don't render a screen if we've never navigated to it + return null; + } + + const isFocused = navigation.state.index === index; + const descriptor = this.props.descriptors[route.key]; + + return ( + + + + ); + })} + ); } } + +const styles = StyleSheet.create({ + pages: { + flex: 1, + }, +}); diff --git a/packages/drawer/src/views/ResourceSavingScene.js b/packages/drawer/src/views/ResourceSavingScene.js new file mode 100644 index 00000000..f5d70767 --- /dev/null +++ b/packages/drawer/src/views/ResourceSavingScene.js @@ -0,0 +1,57 @@ +/* @flow */ + +import * as React from 'react'; +import { Platform, StyleSheet, View } from 'react-native'; + +// eslint-disable-next-line import/no-unresolved +import { Screen, screensEnabled } from 'react-native-screens'; + +type Props = { + isVisible: boolean, + children: React.Node, + style?: any, +}; + +const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container + +export default class ResourceSavingScene extends React.Component { + render() { + if (screensEnabled && screensEnabled()) { + const { isVisible, ...rest } = this.props; + return ; + } + const { isVisible, children, style, ...rest } = this.props; + + return ( + + + {children} + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + overflow: 'hidden', + }, + attached: { + flex: 1, + }, + detached: { + flex: 1, + top: FAR_FAR_AWAY, + }, +});