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 @@ -69,7 +69,6 @@ import { type StateContainer, type StateChange, - setStateForContainer, } from '../utils/state-container.js'; import EthereumLogo from '../vectors/ethereum-logo.react.js'; @@ -232,6 +231,8 @@ type Props = { ...BaseProps, + +logInStateContainer: StateContainer, + +legacyRegisterStateContainer: StateContainer, // Navigation state +isForeground: boolean, // Redux state @@ -248,8 +249,6 @@ type State = { +mode: LoggedOutMode, +nextMode: LoggedOutMode, - +logInState: StateContainer, - +legacyRegisterState: StateContainer, }; class LoggedOutModal extends React.PureComponent { keyboardShowListener: ?EventSubscription; @@ -270,49 +269,10 @@ constructor(props: Props) { super(props); - // Man, this is a lot of boilerplate just to containerize some state. - // Mostly due to Flow typing requirements... - const setLogInState = setStateForContainer( - this.guardedSetState, - (change: Partial) => (fullState: State) => ({ - logInState: { - ...fullState.logInState, - state: { ...fullState.logInState.state, ...change }, - }, - }), - ); - const setLegacyRegisterState = setStateForContainer< - State, - LegacyRegisterState, - >( - this.guardedSetState, - (change: Partial) => (fullState: State) => ({ - legacyRegisterState: { - ...fullState.legacyRegisterState, - state: { ...fullState.legacyRegisterState.state, ...change }, - }, - }), - ); - const initialMode = props.persistedStateLoaded ? 'prompt' : 'loading'; this.state = { mode: initialMode, nextMode: initialMode, - logInState: { - state: { - usernameInputText: null, - passwordInputText: null, - }, - setState: setLogInState, - }, - legacyRegisterState: { - state: { - usernameInputText: '', - passwordInputText: '', - confirmPasswordInputText: '', - }, - setState: setLegacyRegisterState, - }, }; this.nextMode = initialMode; @@ -611,7 +571,7 @@ ); } else if (this.state.mode === 'register') { @@ -619,7 +579,7 @@ ); } else if (this.state.mode === 'prompt') { @@ -787,8 +747,70 @@ LoggedOutModalRouteName, ); +const initialLogInState = { + usernameInputText: null, + passwordInputText: null, +}; +const initialLegacyRegisterState = { + usernameInputText: '', + passwordInputText: '', + confirmPasswordInputText: '', +}; + const ConnectedLoggedOutModal: React.ComponentType = React.memo(function ConnectedLoggedOutModal(props: BaseProps) { + const mountedRef = React.useRef(false); + React.useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + }; + }, []); + + const [logInState, baseSetLogInState] = + React.useState(initialLogInState); + const setLogInState = React.useCallback( + (newLogInState: Partial) => { + if (!mountedRef.current) { + return; + } + baseSetLogInState(prevLogInState => ({ + ...prevLogInState, + ...newLogInState, + })); + }, + [], + ); + const logInStateContainer = React.useMemo( + () => ({ + state: logInState, + setState: setLogInState, + }), + [logInState, setLogInState], + ); + + const [legacyRegisterState, baseSetLegacyRegisterState] = + React.useState(initialLegacyRegisterState); + const setLegacyRegisterState = React.useCallback( + (newLegacyRegisterState: Partial) => { + if (!mountedRef.current) { + return; + } + baseSetLegacyRegisterState(prevLegacyRegisterState => ({ + ...prevLegacyRegisterState, + ...newLegacyRegisterState, + })); + }, + [], + ); + const legacyRegisterStateContainer = React.useMemo( + () => ({ + state: legacyRegisterState, + setState: setLegacyRegisterState, + }), + [legacyRegisterState, setLegacyRegisterState], + ); + const navContext = React.useContext(NavContext); const isForeground = isForegroundSelector(navContext); @@ -806,6 +828,8 @@ return ( = ( +type SimpleStateSetter = ( newState: Partial, callback?: () => mixed, ) => void; export type StateChange = Partial | (S => Partial); -type StateSetter = ( - newState: StateChange, - callback?: () => mixed, -) => void; export type StateContainer = { state: S, setState: SimpleStateSetter, }; - -function setStateForContainer( - setState: StateSetter, - reverseSelector: (ourChange: Partial) => StateChange, -): SimpleStateSetter { - return (ourChange: Partial, callback?: () => mixed) => - setState(reverseSelector(ourChange), callback); -} - -export { setStateForContainer };