diff --git a/packages/react-navigation/src/createNavigationContainer.js b/packages/react-navigation/src/createNavigationContainer.js index 370275e3..59fb591a 100644 --- a/packages/react-navigation/src/createNavigationContainer.js +++ b/packages/react-navigation/src/createNavigationContainer.js @@ -1,10 +1,37 @@ import React from 'react'; import { Linking } from 'react-native'; +import withLifecyclePolyfill from 'react-lifecycles-compat'; + import { BackHandler } from './PlatformHelpers'; import NavigationActions from './NavigationActions'; import addNavigationHelpers from './addNavigationHelpers'; import invariant from './utils/invariant'; +function isStateful(props) { + return !props.navigation; +} + +function validateProps(props) { + if (isStateful(props)) { + return; + } + + const { navigation, screenProps, ...containerProps } = props; + + const keys = Object.keys(containerProps); + + if (keys.length !== 0) { + throw new Error( + 'This navigator has both navigation and container props, so it is ' + + `unclear if it should own its own state. Remove props: "${keys.join( + ', ' + )}" ` + + 'if the navigator should get its state from the navigation prop. If the ' + + 'navigator should maintain its own state, do not pass a navigation prop.' + ); + } +} + /** * Create an HOC that injects the navigation and manages the navigation state * in case it's not passed from above. @@ -18,12 +45,17 @@ export default function createNavigationContainer(Component) { static router = Component.router; static navigationOptions = null; + static getDerivedStateFromProps(nextProps, prevState) { + validateProps(nextProps); + return null; + } + _actionEventSubscribers = new Set(); constructor(props) { super(props); - this._validateProps(props); + validateProps(props); this._initialAction = NavigationActions.init(); @@ -48,28 +80,7 @@ export default function createNavigationContainer(Component) { } _isStateful() { - return !this.props.navigation; - } - - _validateProps(props) { - if (this._isStateful()) { - return; - } - - const { navigation, screenProps, ...containerProps } = props; - - const keys = Object.keys(containerProps); - - if (keys.length !== 0) { - throw new Error( - 'This navigator has both navigation and container props, so it is ' + - `unclear if it should own its own state. Remove props: "${keys.join( - ', ' - )}" ` + - 'if the navigator should get its state from the navigation prop. If the ' + - 'navigator should maintain its own state, do not pass a navigation prop.' - ); - } + return isStateful(this.props); } _urlToPathAndParams(url) { @@ -127,10 +138,6 @@ export default function createNavigationContainer(Component) { } } - componentWillReceiveProps(nextProps) { - this._validateProps(nextProps); - } - componentDidUpdate() { // Clear cached _nav every tick if (this._nav === this.state.nav) { @@ -227,5 +234,5 @@ export default function createNavigationContainer(Component) { } } - return NavigationContainer; + return withLifecyclePolyfill(NavigationContainer); } diff --git a/packages/react-navigation/src/views/Drawer/DrawerView.js b/packages/react-navigation/src/views/Drawer/DrawerView.js index 72eaa868..a8f86a3c 100644 --- a/packages/react-navigation/src/views/Drawer/DrawerView.js +++ b/packages/react-navigation/src/views/Drawer/DrawerView.js @@ -17,7 +17,7 @@ export default class DrawerView extends React.PureComponent { : this.props.navigationConfig.drawerWidth, }; - componentWillMount() { + componentDidMount() { Dimensions.addEventListener('change', this._updateWidth); } @@ -25,9 +25,10 @@ export default class DrawerView extends React.PureComponent { Dimensions.removeEventListener('change', this._updateWidth); } - componentWillReceiveProps(nextProps) { - const { isDrawerOpen } = nextProps.navigation.state; - const wasDrawerOpen = this.props.navigation.state.isDrawerOpen; + componentDidUpdate(prevProps, prevState) { + const { isDrawerOpen } = this.props.navigation.state; + const wasDrawerOpen = prevProps.navigation.state.isDrawerOpen; + if (isDrawerOpen && !wasDrawerOpen) { this._drawer.openDrawer(); } else if (wasDrawerOpen && !isDrawerOpen) { diff --git a/packages/react-navigation/src/views/ResourceSavingSceneView.js b/packages/react-navigation/src/views/ResourceSavingSceneView.js index d9f0e7c8..63b4f4ac 100644 --- a/packages/react-navigation/src/views/ResourceSavingSceneView.js +++ b/packages/react-navigation/src/views/ResourceSavingSceneView.js @@ -8,6 +8,14 @@ import SceneView from './SceneView'; const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container class ResourceSavingSceneView extends React.PureComponent { + static getDerivedStateFromProps(nextProps, prevState) { + if (nextProps.isFocused && !prevState.awake) { + return { awake: true }; + } else { + return null; + } + } + constructor(props) { super(); @@ -16,14 +24,6 @@ class ResourceSavingSceneView extends React.PureComponent { }; } - static getDerivedStateFromProps(nextProps, prevState) { - if (nextProps.isFocused && !prevState.awake) { - return { awake: true }; - } - - return null; - } - render() { const { awake } = this.state; const { diff --git a/packages/react-navigation/src/views/StackView/StackViewLayout.js b/packages/react-navigation/src/views/StackView/StackViewLayout.js index b4123211..8ec384e7 100644 --- a/packages/react-navigation/src/views/StackView/StackViewLayout.js +++ b/packages/react-navigation/src/views/StackView/StackViewLayout.js @@ -352,7 +352,7 @@ class StackViewLayout extends React.Component { return ( - {scenes.map((s: *) => this._renderCard(s))} + {scenes.map(s => this._renderCard(s))} {floatingHeader} diff --git a/packages/react-navigation/src/views/StackView/createPointerEventsContainer.js b/packages/react-navigation/src/views/StackView/createPointerEventsContainer.js index 045a012f..8564fe1a 100644 --- a/packages/react-navigation/src/views/StackView/createPointerEventsContainer.js +++ b/packages/react-navigation/src/views/StackView/createPointerEventsContainer.js @@ -16,25 +16,14 @@ export default function createPointerEventsContainer(Component) { this._pointerEvents = this._computePointerEvents(); } - componentWillMount() { - this._onPositionChange = this._onPositionChange.bind(this); - this._onComponentRef = this._onComponentRef.bind(this); - } - - componentDidMount() { - this._bindPosition(this.props); - } - componentWillUnmount() { this._positionListener && this._positionListener.remove(); } - componentWillReceiveProps(nextProps) { - this._bindPosition(nextProps); - } - render() { + this._bindPosition(); this._pointerEvents = this._computePointerEvents(); + return ( { this._component = component; if (component) { invariant( @@ -52,17 +41,17 @@ export default function createPointerEventsContainer(Component) { 'component must implement method `setNativeProps`' ); } - } + }; - _bindPosition(props) { + _bindPosition() { this._positionListener && this._positionListener.remove(); this._positionListener = new AnimatedValueSubscription( - props.position, + this.props.position, this._onPositionChange ); } - _onPositionChange() { + _onPositionChange = () => { if (this._component) { const pointerEvents = this._computePointerEvents(); if (this._pointerEvents !== pointerEvents) { @@ -70,7 +59,7 @@ export default function createPointerEventsContainer(Component) { this._component.setNativeProps({ pointerEvents }); } } - } + }; _computePointerEvents() { const { navigation, position, scene } = this.props;