import debounce from 'debounce'; import React from 'react'; import { Animated, View } from 'react-native'; let _shouldUseScreens = true; export function useScreens(shouldUseScreens = true) { if (shouldUseScreens) { console.warn( 'react-native-screens is not fully supported on this platform yet.' ); } _shouldUseScreens = shouldUseScreens; } export function screensEnabled() { return _shouldUseScreens; } function isAnimatedValue(value) { return value && value.__getValue && value.addListener; } function isPropTruthy(prop) { let activeValue = prop; if (isAnimatedValue(prop)) { activeValue = prop.__getValue(); } return !!activeValue; } export class Screen extends React.Component { static defaultProps = { active: true, }; listenerId = null; constructor(props) { super(props); this._onAnimatedValueUpdated = debounce(this._onAnimatedValueUpdated, 10); this._addListener(props.active); } componentWillUnmount() { this._removeListener(this.props.active); } _addListener = possibleListener => { if (this.listenerId) throw new Error( 'Screen: Attempting to observe an animated value while another value is already observed.' ); if (isAnimatedValue(possibleListener)) { this.listenerId = possibleListener.addListener( this._onAnimatedValueUpdated ); } }; _removeListener = possibleListener => { if (isAnimatedValue(possibleListener)) { possibleListener.removeListener(this.listenerId); this.listenerId = null; } }; shouldComponentUpdate({ active: nextActive }) { const { active } = this.props; if (nextActive !== active) { this._removeListener(active); this._addListener(nextActive); this._updateDisplay(isPropTruthy(nextActive)); return false; } return true; } _onAnimatedValueUpdated = ({ value }) => { this._updateDisplay(!!value); }; _updateDisplay = isActive => { if (isActive === undefined) { isActive = isPropTruthy(this.props.active); } const display = isActive ? 'flex' : 'none'; this.setNativeProps({ style: { display } }); }; setNativeProps = nativeProps => { if (this._view) { this._view.setNativeProps(nativeProps); } }; _setRef = view => { this._view = view; this._updateDisplay(); }; render() { return <Animated.View {...this.props} ref={this._setRef} />; } } export const ScreenContainer = View; export const NativeScreen = View; export const NativeScreenContainer = View;