diff --git a/native/account/logged-out-modal.react.js b/native/account/logged-out-modal.react.js --- a/native/account/logged-out-modal.react.js +++ b/native/account/logged-out-modal.react.js @@ -66,10 +66,7 @@ runTiming, ratchetAlongWithKeyboardHeight, } from '../utils/animation-utils.js'; -import { - type StateContainer, - type StateChange, -} from '../utils/state-container.js'; +import type { StateContainer } from '../utils/state-container.js'; import EthereumLogo from '../vectors/ethereum-logo.react.js'; let initialAppLoad = true; @@ -233,6 +230,8 @@ ...BaseProps, +logInStateContainer: StateContainer, +legacyRegisterStateContainer: StateContainer, + +mode: Mode, + +setMode: (Partial) => void, // Navigation state +isForeground: boolean, // Redux state @@ -246,15 +245,10 @@ // Redux dispatch functions +dispatch: Dispatch, }; -type State = { - +mode: LoggedOutMode, - +nextMode: LoggedOutMode, -}; -class LoggedOutModal extends React.PureComponent { +class LoggedOutModal extends React.PureComponent { keyboardShowListener: ?EventSubscription; keyboardHideListener: ?EventSubscription; - mounted = false; nextMode: LoggedOutMode = 'loading'; activeAlert = false; @@ -269,12 +263,7 @@ constructor(props: Props) { super(props); - const initialMode = props.persistedStateLoaded ? 'prompt' : 'loading'; - this.state = { - mode: initialMode, - nextMode: initialMode, - }; - this.nextMode = initialMode; + this.nextMode = props.mode.curMode; this.contentHeight = new Value(props.dimensions.safeAreaHeight); this.modeValue = new Value(modeNumbers[this.nextMode]); @@ -284,24 +273,17 @@ this.panelOpacityValue = this.panelOpacity(); } - guardedSetState = (change: StateChange, callback?: () => mixed) => { - if (this.mounted) { - this.setState(change, callback); - } - }; - setMode(newMode: LoggedOutMode) { this.nextMode = newMode; - this.guardedSetState({ mode: newMode, nextMode: newMode }); + this.props.setMode({ curMode: newMode, nextMode: newMode }); this.modeValue.setValue(modeNumbers[newMode]); } proceedToNextMode = () => { - this.guardedSetState({ mode: this.nextMode }); + this.props.setMode({ curMode: this.nextMode }); }; componentDidMount() { - this.mounted = true; if (this.props.rehydrateConcluded) { this.onInitialAppLoad(); } @@ -311,13 +293,12 @@ } componentWillUnmount() { - this.mounted = false; if (this.props.isForeground) { this.onBackground(); } } - componentDidUpdate(prevProps: Props, prevState: State) { + componentDidUpdate(prevProps: Props) { if (!prevProps.persistedStateLoaded && this.props.persistedStateLoaded) { this.setMode('prompt'); } @@ -330,7 +311,10 @@ this.onBackground(); } - if (this.state.mode === 'prompt' && prevState.mode !== 'prompt') { + if ( + this.props.mode.curMode === 'prompt' && + prevProps.mode.curMode !== 'prompt' + ) { this.buttonOpacity.setValue(0); Animated.timing(this.buttonOpacity, { easing: EasingNode.out(EasingNode.ease), @@ -533,7 +517,7 @@ goBackToPrompt = () => { this.nextMode = 'prompt'; - this.guardedSetState({ nextMode: 'prompt' }); + this.props.setMode({ nextMode: 'prompt' }); this.keyboardHeightValue.setValue(0); this.modeValue.setValue(modeNumbers['prompt']); Keyboard.dismiss(); @@ -566,7 +550,7 @@ let panel = null; let buttons = null; - if (this.state.mode === 'log-in') { + if (this.props.mode.curMode === 'log-in') { panel = ( ); - } else if (this.state.mode === 'register') { + } else if (this.props.mode.curMode === 'register') { panel = ( ); - } else if (this.state.mode === 'prompt') { + } else if (this.props.mode.curMode === 'prompt') { const opacityStyle = { opacity: this.buttonOpacity }; const registerButtons = []; @@ -649,7 +633,7 @@ {registerButtons} ); - } else if (this.state.mode === 'loading') { + } else if (this.props.mode.curMode === 'loading') { panel = ( ); } @@ -757,6 +741,11 @@ confirmPasswordInputText: '', }; +type Mode = { + +curMode: LoggedOutMode, + +nextMode: LoggedOutMode, +}; + const ConnectedLoggedOutModal: React.ComponentType = React.memo(function ConnectedLoggedOutModal(props: BaseProps) { const mountedRef = React.useRef(false); @@ -811,13 +800,28 @@ [legacyRegisterState, setLegacyRegisterState], ); + const persistedStateLoaded = usePersistedStateLoaded(); + const initialMode = persistedStateLoaded ? 'prompt' : 'loading'; + const [mode, baseSetMode] = React.useState(() => ({ + curMode: initialMode, + nextMode: initialMode, + })); + const setMode = React.useCallback((newMode: Partial) => { + if (!mountedRef.current) { + return; + } + baseSetMode(prevMode => ({ + ...prevMode, + ...newMode, + })); + }, []); + const navContext = React.useContext(NavContext); const isForeground = isForegroundSelector(navContext); const rehydrateConcluded = useSelector( state => !!(state._persist && state._persist.rehydrated && navContext), ); - const persistedStateLoaded = usePersistedStateLoaded(); const cookie = useSelector(cookieSelector(authoritativeKeyserverID)); const loggedIn = useSelector(isLoggedIn); const dimensions = useSelector(derivedDimensionsInfoSelector); @@ -830,6 +834,8 @@ {...props} logInStateContainer={logInStateContainer} legacyRegisterStateContainer={legacyRegisterStateContainer} + mode={mode} + setMode={setMode} isForeground={isForeground} persistedStateLoaded={persistedStateLoaded} rehydrateConcluded={rehydrateConcluded} diff --git a/native/utils/state-container.js b/native/utils/state-container.js --- a/native/utils/state-container.js +++ b/native/utils/state-container.js @@ -5,8 +5,6 @@ callback?: () => mixed, ) => void; -export type StateChange = Partial | (S => Partial); - export type StateContainer = { state: S, setState: SimpleStateSetter,