diff --git a/lib/socket/calendar-query-handler.react.js b/lib/socket/calendar-query-handler.react.js index ba716e43a..f23539f37 100644 --- a/lib/socket/calendar-query-handler.react.js +++ b/lib/socket/calendar-query-handler.react.js @@ -1,140 +1,144 @@ // @flow import _isEqual from 'lodash/fp/isEqual'; -import PropTypes from 'prop-types'; import * as React from 'react'; import { updateCalendarQueryActionTypes, updateCalendarQuery, } from '../actions/entry-actions'; import { timeUntilCalendarRangeExpiration } from '../selectors/nav-selectors'; import type { CalendarQuery, CalendarQueryUpdateResult, CalendarQueryUpdateStartingPayload, } from '../types/entry-types'; -import type { BaseAppState } from '../types/redux-types'; +import { type ConnectionInfo } from '../types/socket-types'; import { - type ConnectionInfo, - connectionInfoPropType, -} from '../types/socket-types'; -import type { DispatchActionPromise } from '../utils/action-utils'; -import { connect } from '../utils/redux-utils'; + type DispatchActionPromise, + useDispatchActionPromise, + useServerCall, +} from '../utils/action-utils'; +import { useSelector } from '../utils/redux-utils'; +type BaseProps = {| + +currentCalendarQuery: () => CalendarQuery, + +frozen: boolean, +|}; type Props = {| - currentCalendarQuery: () => CalendarQuery, - frozen: boolean, - // Redux state - connection: ConnectionInfo, - lastUserInteractionCalendar: number, - foreground: boolean, - // Redux dispatch functions - dispatchActionPromise: DispatchActionPromise, - // async functions that hit server APIs - updateCalendarQuery: ( + ...BaseProps, + +connection: ConnectionInfo, + +lastUserInteractionCalendar: number, + +foreground: boolean, + +dispatchActionPromise: DispatchActionPromise, + +updateCalendarQuery: ( calendarQuery: CalendarQuery, reduxAlreadyUpdated?: boolean, ) => Promise, |}; class CalendarQueryHandler extends React.PureComponent { - static propTypes = { - currentCalendarQuery: PropTypes.func.isRequired, - frozen: PropTypes.bool.isRequired, - connection: connectionInfoPropType.isRequired, - lastUserInteractionCalendar: PropTypes.number.isRequired, - foreground: PropTypes.bool.isRequired, - dispatchActionPromise: PropTypes.func.isRequired, - updateCalendarQuery: PropTypes.func.isRequired, - }; serverCalendarQuery: CalendarQuery; expirationTimeoutID: ?TimeoutID; constructor(props: Props) { super(props); this.serverCalendarQuery = this.props.connection.actualizedCalendarQuery; } componentDidMount() { if (this.props.connection.status === 'connected') { this.possiblyUpdateCalendarQuery(); } } componentDidUpdate(prevProps: Props) { const { actualizedCalendarQuery } = this.props.connection; if (this.props.connection.status !== 'connected') { if (!_isEqual(this.serverCalendarQuery)(actualizedCalendarQuery)) { this.serverCalendarQuery = actualizedCalendarQuery; } return; } if ( !_isEqual(this.serverCalendarQuery)(actualizedCalendarQuery) && _isEqual(this.props.currentCalendarQuery())(actualizedCalendarQuery) ) { this.serverCalendarQuery = actualizedCalendarQuery; } const shouldUpdate = (this.isExpired || prevProps.connection.status !== 'connected' || this.props.currentCalendarQuery !== prevProps.currentCalendarQuery) && this.shouldUpdateCalendarQuery; if (shouldUpdate) { this.updateCalendarQuery(); } } render() { return null; } get isExpired() { const timeUntilExpiration = timeUntilCalendarRangeExpiration( this.props.lastUserInteractionCalendar, ); return ( timeUntilExpiration !== null && timeUntilExpiration !== undefined && timeUntilExpiration <= 0 ); } get shouldUpdateCalendarQuery() { if (this.props.connection.status !== 'connected' || this.props.frozen) { return false; } const calendarQuery = this.props.currentCalendarQuery(); return !_isEqual(calendarQuery)(this.serverCalendarQuery); } updateCalendarQuery() { const calendarQuery = this.props.currentCalendarQuery(); this.serverCalendarQuery = calendarQuery; this.props.dispatchActionPromise( updateCalendarQueryActionTypes, this.props.updateCalendarQuery(calendarQuery, true), undefined, ({ calendarQuery }: CalendarQueryUpdateStartingPayload), ); } possiblyUpdateCalendarQuery = () => { if (this.shouldUpdateCalendarQuery) { this.updateCalendarQuery(); } }; } -export default connect( - (state: BaseAppState<*>) => ({ - connection: state.connection, - lastUserInteractionCalendar: state.entryStore.lastUserInteractionCalendar, - // We include this so that componentDidUpdate will be called on foreground - foreground: state.foreground, - }), - { updateCalendarQuery }, -)(CalendarQueryHandler); +export default React.memo(function ConnectedCalendarQueryHandler( + props: BaseProps, +) { + const connection = useSelector((state) => state.connection); + const lastUserInteractionCalendar = useSelector( + (state) => state.entryStore.lastUserInteractionCalendar, + ); + // We include this so that componentDidUpdate will be called on foreground + const foreground = useSelector((state) => state.foreground); + const callUpdateCalendarQuery = useServerCall(updateCalendarQuery); + const dispatchActionPromise = useDispatchActionPromise(); + + return ( + + ); +});