diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js
index 037fb3afae73..efb64fbb5397 100644
--- a/src/components/PressableWithSecondaryInteraction/index.js
+++ b/src/components/PressableWithSecondaryInteraction/index.js
@@ -17,8 +17,12 @@ class PressableWithSecondaryInteraction extends Component {
}
componentDidMount() {
- if (this.props.forwardedRef && _.isFunction(this.props.forwardedRef)) {
- this.props.forwardedRef(this.pressableRef);
+ if (this.props.forwardedRef) {
+ if (_.isFunction(this.props.forwardedRef)) {
+ this.props.forwardedRef(this.pressableRef);
+ } else if (_.isObject(this.props.forwardedRef)) {
+ this.props.forwardedRef.current = this.pressableRef;
+ }
}
this.pressableRef.addEventListener('contextmenu', this.executeSecondaryInteractionOnContextMenu);
}
diff --git a/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js b/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js
index e54598cb1394..b036404e018d 100644
--- a/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js
+++ b/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
+import refPropTypes from '../refPropTypes';
import stylePropTypes from '../../styles/stylePropTypes';
const propTypes = {
@@ -18,7 +19,7 @@ const propTypes = {
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
/** The ref to the search input (may be null on small screen widths) */
- forwardedRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
+ forwardedRef: refPropTypes,
/** Prevent the default ContextMenu on web/Desktop */
preventDefaultContextMenu: PropTypes.bool,
diff --git a/src/components/ReportActionItem/IOUPreview.js b/src/components/ReportActionItem/IOUPreview.js
index 9e8863fe9953..108cc5fc5339 100644
--- a/src/components/ReportActionItem/IOUPreview.js
+++ b/src/components/ReportActionItem/IOUPreview.js
@@ -27,6 +27,7 @@ import * as OptionsListUtils from '../../libs/OptionsListUtils';
import * as CurrencyUtils from '../../libs/CurrencyUtils';
import * as IOUUtils from '../../libs/IOUUtils';
import * as ReportUtils from '../../libs/ReportUtils';
+import refPropTypes from '../refPropTypes';
const propTypes = {
/** The active IOUReport, used for Onyx subscription */
@@ -43,7 +44,7 @@ const propTypes = {
action: PropTypes.shape(reportActionPropTypes),
/** Popover context menu anchor, used for showing context menu */
- contextMenuAnchor: PropTypes.shape({current: PropTypes.elementType}),
+ contextMenuAnchor: refPropTypes,
/** Callback for updating context menu active state, used for showing context menu */
checkIfContextMenuActive: PropTypes.func,
diff --git a/src/components/ReportActionItem/MoneyRequestAction.js b/src/components/ReportActionItem/MoneyRequestAction.js
index 03a5f047275e..76cf17469496 100644
--- a/src/components/ReportActionItem/MoneyRequestAction.js
+++ b/src/components/ReportActionItem/MoneyRequestAction.js
@@ -20,6 +20,7 @@ import * as ReportUtils from '../../libs/ReportUtils';
import * as Report from '../../libs/actions/Report';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import * as ReportActionsUtils from '../../libs/ReportActionsUtils';
+import refPropTypes from '../refPropTypes';
const propTypes = {
/** All the data of the action */
@@ -35,7 +36,7 @@ const propTypes = {
isMostRecentIOUReportAction: PropTypes.bool.isRequired,
/** Popover context menu anchor, used for showing context menu */
- contextMenuAnchor: PropTypes.shape({current: PropTypes.elementType}),
+ contextMenuAnchor: refPropTypes,
/** Callback for updating context menu active state, used for showing context menu */
checkIfContextMenuActive: PropTypes.func,
diff --git a/src/components/ReportActionItem/ReportPreview.js b/src/components/ReportActionItem/ReportPreview.js
index 9758c6ab61d4..4c85be327bba 100644
--- a/src/components/ReportActionItem/ReportPreview.js
+++ b/src/components/ReportActionItem/ReportPreview.js
@@ -24,6 +24,7 @@ import SettlementButton from '../SettlementButton';
import themeColors from '../../styles/themes/default';
import getButtonState from '../../libs/getButtonState';
import * as IOU from '../../libs/actions/IOU';
+import refPropTypes from '../refPropTypes';
const propTypes = {
/** All the data of the action */
@@ -71,7 +72,7 @@ const propTypes = {
}),
/** Popover context menu anchor, used for showing context menu */
- contextMenuAnchor: PropTypes.shape({current: PropTypes.elementType}),
+ contextMenuAnchor: refPropTypes,
/** Callback for updating context menu active state, used for showing context menu */
checkIfContextMenuActive: PropTypes.func,
diff --git a/src/components/refPropTypes.js b/src/components/refPropTypes.js
new file mode 100644
index 000000000000..a67f6323d1d9
--- /dev/null
+++ b/src/components/refPropTypes.js
@@ -0,0 +1,3 @@
+import PropTypes from 'prop-types';
+
+export default PropTypes.oneOfType([PropTypes.func, PropTypes.object]);
diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js
index e1acc7ecd736..1cc5a6e3b220 100644
--- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js
+++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js
@@ -95,7 +95,7 @@ class PopoverReportActionContextMenu extends React.Component {
getContextMenuMeasuredLocation() {
return new Promise((resolve) => {
if (this.contextMenuAnchor) {
- this.contextMenuAnchor.measureInWindow((x, y) => resolve({x, y}));
+ this.contextMenuAnchor.current.measureInWindow((x, y) => resolve({x, y}));
} else {
resolve({x: 0, y: 0});
}
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index a0511469fa4a..a318d181e460 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -1,6 +1,6 @@
import _ from 'underscore';
import lodashGet from 'lodash/get';
-import React, {Component} from 'react';
+import React, {useState, useRef, useEffect, memo, useCallback} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
@@ -66,9 +66,6 @@ const propTypes = {
/** Is this the most recent IOU Action? */
isMostRecentIOUReportAction: PropTypes.bool.isRequired,
- /** Whether there is an outstanding amount in IOU */
- hasOutstandingIOU: PropTypes.bool,
-
/** Should we display the new marker on top of the comment? */
shouldDisplayNewMarker: PropTypes.bool.isRequired,
@@ -81,6 +78,10 @@ const propTypes = {
/** Draft message - if this is set the comment is in 'edit' mode */
draftMessage: PropTypes.string,
+ /* Whether the option has an outstanding IOU */
+ // eslint-disable-next-line react/no-unused-prop-types
+ hasOutstandingIOU: PropTypes.bool,
+
/** Stores user's preferred skin tone */
preferredSkinTone: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
@@ -95,105 +96,89 @@ const propTypes = {
const defaultProps = {
draftMessage: '',
- hasOutstandingIOU: false,
preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE,
personalDetails: {},
shouldShowSubscriptAvatar: false,
+ hasOutstandingIOU: false,
betas: [],
};
-class ReportActionItem extends Component {
- constructor(props) {
- super(props);
- this.popoverAnchor = undefined;
- this.state = {
- isContextMenuActive: ReportActionContextMenu.isActiveReportAction(props.action.reportActionID),
- };
- this.checkIfContextMenuActive = this.checkIfContextMenuActive.bind(this);
- this.showPopover = this.showPopover.bind(this);
- this.renderItemContent = this.renderItemContent.bind(this);
- this.toggleReaction = this.toggleReaction.bind(this);
- }
-
- shouldComponentUpdate(nextProps, nextState) {
- return (
- this.props.displayAsGroup !== nextProps.displayAsGroup ||
- this.props.draftMessage !== nextProps.draftMessage ||
- this.props.isMostRecentIOUReportAction !== nextProps.isMostRecentIOUReportAction ||
- this.props.hasOutstandingIOU !== nextProps.hasOutstandingIOU ||
- this.props.shouldDisplayNewMarker !== nextProps.shouldDisplayNewMarker ||
- !_.isEqual(this.props.action, nextProps.action) ||
- this.state.isContextMenuActive !== nextState.isContextMenuActive ||
- lodashGet(this.props.report, 'statusNum') !== lodashGet(nextProps.report, 'statusNum') ||
- lodashGet(this.props.report, 'stateNum') !== lodashGet(nextProps.report, 'stateNum') ||
- this.props.translate !== nextProps.translate
- );
- }
+function ReportActionItem(props) {
+ const [isContextMenuActive, setIsContextMenuActive] = useState(ReportActionContextMenu.isActiveReportAction(props.action.reportActionID));
+ const textInputRef = useRef();
+ const popoverAnchorRef = useRef();
- componentDidUpdate(prevProps) {
- if (prevProps.draftMessage || !this.props.draftMessage) {
+ const isDraftEmpty = !props.draftMessage;
+ useEffect(() => {
+ if (isDraftEmpty) {
return;
}
// Only focus the input when user edits a message, skip it for existing drafts being edited of the report.
// There is an animation when the comment is hidden and the edit form is shown, and there can be bugs on different mobile platforms
// if the input is given focus in the middle of that animation which can prevent the keyboard from opening.
- focusTextInputAfterAnimation(this.textInput, 100);
- }
+ focusTextInputAfterAnimation(textInputRef.current, 100);
+ }, [isDraftEmpty]);
- checkIfContextMenuActive() {
- this.setState({isContextMenuActive: ReportActionContextMenu.isActiveReportAction(this.props.action.reportActionID)});
- }
+ const toggleContextMenuFromActiveReportAction = useCallback(() => {
+ setIsContextMenuActive(ReportActionContextMenu.isActiveReportAction(props.action.reportActionID));
+ }, [props.action.reportActionID]);
/**
* Show the ReportActionContextMenu modal popover.
*
* @param {Object} [event] - A press event.
*/
- showPopover(event) {
- // Block menu on the message being Edited or if the report action item has errors
- if (this.props.draftMessage || !_.isEmpty(this.props.action.errors)) {
- return;
- }
-
- this.setState({isContextMenuActive: true});
-
- const selection = SelectionScraper.getCurrentSelection();
- ReportActionContextMenu.showContextMenu(
- ContextMenuActions.CONTEXT_MENU_TYPES.REPORT_ACTION,
- event,
- selection,
- this.popoverAnchor,
- this.props.report.reportID,
- this.props.action,
- this.props.draftMessage,
- undefined,
- this.checkIfContextMenuActive,
- ReportUtils.isArchivedRoom(this.props.report),
- ReportUtils.chatIncludesChronos(this.props.report),
- this.props.action.childReportID,
- );
- }
+ const showPopover = useCallback(
+ (event) => {
+ // Block menu on the message being Edited or if the report action item has errors
+ if (props.draftMessage || !_.isEmpty(props.action.errors)) {
+ return;
+ }
+
+ setIsContextMenuActive(true);
+
+ const selection = SelectionScraper.getCurrentSelection();
+ ReportActionContextMenu.showContextMenu(
+ ContextMenuActions.CONTEXT_MENU_TYPES.REPORT_ACTION,
+ event,
+ selection,
+ popoverAnchorRef,
+ props.report.reportID,
+ props.action,
+ props.draftMessage,
+ () => {},
+ toggleContextMenuFromActiveReportAction,
+ ReportUtils.isArchivedRoom(props.report),
+ ReportUtils.chatIncludesChronos(props.report),
+ props.action.childReportID,
+ );
+ },
+ [props.draftMessage, props.action, props.report, toggleContextMenuFromActiveReportAction],
+ );
- toggleReaction(emoji) {
- Report.toggleEmojiReaction(this.props.report.reportID, this.props.action, emoji);
- }
+ const toggleReaction = useCallback(
+ (emoji) => {
+ Report.toggleEmojiReaction(props.report.reportID, props.action, emoji);
+ },
+ [props.report, props.action],
+ );
/**
* Get the content of ReportActionItem
* @param {Boolean} hovered whether the ReportActionItem is hovered
* @returns {Object} child component(s)
*/
- renderItemContent(hovered = false) {
+ const renderItemContent = (hovered = false) => {
let children;
- const originalMessage = lodashGet(this.props.action, 'originalMessage', {});
+ const originalMessage = lodashGet(props.action, 'originalMessage', {});
// IOUDetails only exists when we are sending money
const isSendingMoney = originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && _.has(originalMessage, 'IOUDetails');
// Show the IOUPreview for when request was created, bill was split or money was sent
if (
- this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU &&
+ props.action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU &&
originalMessage &&
// For the pay flow, we only want to show MoneyRequestAction when sending money. When paying, we display a regular system message
(originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE || originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.SPLIT || isSendingMoney)
@@ -202,82 +187,79 @@ class ReportActionItem extends Component {
const iouReportID = originalMessage.IOUReportID ? originalMessage.IOUReportID.toString() : '0';
children = (
);
- } else if (this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW) {
+ } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW) {
children = (
);
} else if (
- this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED ||
- this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCANCELED ||
- this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKREOPENED
+ props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED ||
+ props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCANCELED ||
+ props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKREOPENED
) {
children = (
);
- } else if (ReportActionsUtils.isCreatedTaskReportAction(this.props.action)) {
+ } else if (ReportActionsUtils.isCreatedTaskReportAction(props.action)) {
children = (
);
} else {
- const message = _.last(lodashGet(this.props.action, 'message', [{}]));
- const isAttachment = _.has(this.props.action, 'isAttachment') ? this.props.action.isAttachment : ReportUtils.isReportMessageAttachment(message);
+ const message = _.last(lodashGet(props.action, 'message', [{}]));
+ const isAttachment = _.has(props.action, 'isAttachment') ? props.action.isAttachment : ReportUtils.isReportMessageAttachment(message);
children = (
- {!this.props.draftMessage ? (
+ {!props.draftMessage ? (
) : (
(this.textInput = el)}
- report={this.props.report}
+ action={props.action}
+ draftMessage={props.draftMessage}
+ reportID={props.report.reportID}
+ index={props.index}
+ ref={textInputRef}
+ report={props.report}
// Avoid defining within component due to an existing Onyx bug
- preferredSkinTone={this.props.preferredSkinTone}
+ preferredSkinTone={props.preferredSkinTone}
shouldDisableEmojiPicker={
- (ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge)) ||
- ReportUtils.isArchivedRoom(this.props.report)
+ (ReportUtils.chatIncludesConcierge(props.report) && User.isBlockedFromConcierge(props.blockedFromConcierge)) || ReportUtils.isArchivedRoom(props.report)
}
/>
)}
@@ -285,42 +267,39 @@ class ReportActionItem extends Component {
);
}
- const reactions = _.get(this.props, ['action', 'message', 0, 'reactions'], []);
+ const reactions = _.get(props, ['action', 'message', 0, 'reactions'], []);
const hasReactions = reactions.length > 0;
- const numberOfThreadReplies = _.get(this.props, ['action', 'childVisibleActionCount'], 0);
+ const numberOfThreadReplies = _.get(props, ['action', 'childVisibleActionCount'], 0);
const hasReplies = numberOfThreadReplies > 0;
const shouldDisplayThreadReplies =
- hasReplies &&
- this.props.action.childCommenterCount &&
- Permissions.canUseThreads(this.props.betas) &&
- !ReportUtils.isThreadFirstChat(this.props.action, this.props.report.reportID);
- const oldestFourEmails = lodashGet(this.props.action, 'childOldestFourEmails', '').split(',');
+ hasReplies && props.action.childCommenterCount && Permissions.canUseThreads(props.betas) && !ReportUtils.isThreadFirstChat(props.action, props.report.reportID);
+ const oldestFourEmails = lodashGet(props.action, 'childOldestFourEmails', '').split(',');
return (
<>
{children}
{hasReactions && (
-
+
)}
{shouldDisplayThreadReplies && (
)}
>
);
- }
+ };
/**
* Get ReportActionItem with a proper wrapper
@@ -328,21 +307,21 @@ class ReportActionItem extends Component {
* @param {Boolean} isWhisper whether the ReportActionItem is a whisper
* @returns {Object} report action item
*/
- renderReportActionItem(hovered, isWhisper) {
- const content = this.renderItemContent(hovered || this.state.isContextMenuActive);
+ const renderReportActionItem = (hovered, isWhisper) => {
+ const content = renderItemContent(hovered || isContextMenuActive);
- if (this.props.draftMessage) {
+ if (props.draftMessage) {
return {content};
}
- if (!this.props.displayAsGroup) {
+ if (!props.displayAsGroup) {
return (
{content}
@@ -350,102 +329,101 @@ class ReportActionItem extends Component {
}
return {content};
- }
+ };
- render() {
- if (this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) {
- return ;
- }
- if (this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED) {
- return ;
- }
- if (this.props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CHRONOSOOOLIST) {
- return (
-
- );
- }
-
- const hasErrors = !_.isEmpty(this.props.action.errors);
- const whisperedTo = lodashGet(this.props.action, 'whisperedTo', []);
- const isWhisper = whisperedTo.length > 0;
- const isMultipleParticipant = whisperedTo.length > 1;
- const isWhisperOnlyVisibleByUser = isWhisper && ReportUtils.isCurrentUserTheOnlyParticipant(whisperedTo);
- const whisperedToPersonalDetails = isWhisper ? _.filter(this.props.personalDetails, (details) => _.includes(whisperedTo, details.login)) : [];
- const displayNamesWithTooltips = isWhisper ? ReportUtils.getDisplayNamesWithTooltips(whisperedToPersonalDetails, isMultipleParticipant) : [];
+ if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) {
+ return ;
+ }
+ if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED) {
+ return ;
+ }
+ if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CHRONOSOOOLIST) {
return (
- (this.popoverAnchor = el)}
- onPressIn={() => this.props.isSmallScreenWidth && DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()}
- onPressOut={() => ControlSelection.unblock()}
- onSecondaryInteraction={this.showPopover}
- preventDefaultContextMenu={!this.props.draftMessage && !hasErrors}
- withoutFocusOnSecondaryInteraction
- >
-
- {(hovered) => (
-
- {this.props.shouldDisplayNewMarker && }
-
-
+ );
+ }
+
+ const hasErrors = !_.isEmpty(props.action.errors);
+ const whisperedTo = lodashGet(props.action, 'whisperedTo', []);
+ const isWhisper = whisperedTo.length > 0;
+ const isMultipleParticipant = whisperedTo.length > 1;
+ const isWhisperOnlyVisibleByUser = isWhisper && ReportUtils.isCurrentUserTheOnlyParticipant(whisperedTo);
+ const whisperedToPersonalDetails = isWhisper ? _.filter(props.personalDetails, (details) => _.includes(whisperedTo, details.login)) : [];
+ const displayNamesWithTooltips = isWhisper ? ReportUtils.getDisplayNamesWithTooltips(whisperedToPersonalDetails, isMultipleParticipant) : [];
+ return (
+ props.isSmallScreenWidth && DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()}
+ onPressOut={() => ControlSelection.unblock()}
+ onSecondaryInteraction={showPopover}
+ preventDefaultContextMenu={!props.draftMessage && !hasErrors}
+ withoutFocusOnSecondaryInteraction
+ >
+
+ {(hovered) => (
+
+ {props.shouldDisplayNewMarker && }
+
+
+ ReportActions.clearReportActionErrors(props.report.reportID, props.action)}
+ pendingAction={props.draftMessage ? null : props.action.pendingAction}
+ errors={props.action.errors}
+ errorRowStyles={[styles.ml10, styles.mr2]}
+ needsOffscreenAlphaCompositing={ReportActionsUtils.isMoneyRequestAction(props.action)}
>
- ReportActions.clearReportActionErrors(this.props.report.reportID, this.props.action)}
- pendingAction={this.props.draftMessage ? null : this.props.action.pendingAction}
- errors={this.props.action.errors}
- errorRowStyles={[styles.ml10, styles.mr2]}
- needsOffscreenAlphaCompositing={ReportActionsUtils.isMoneyRequestAction(this.props.action)}
- >
- {isWhisper && (
-
-
-
-
-
- {this.props.translate('reportActionContextMenu.onlyVisible')}
-
-
-
+
+
- )}
- {this.renderReportActionItem(hovered, isWhisper)}
-
-
+
+ {props.translate('reportActionContextMenu.onlyVisible')}
+
+
+
+
+ )}
+ {renderReportActionItem(hovered, isWhisper)}
+
- )}
-
-
-
-
-
- );
- }
+
+ )}
+
+
+
+
+
+ );
}
+
ReportActionItem.propTypes = propTypes;
ReportActionItem.defaultProps = defaultProps;
@@ -470,4 +448,18 @@ export default compose(
key: ONYXKEYS.BETAS,
},
}),
-)(ReportActionItem);
+)(
+ memo(
+ ReportActionItem,
+ (prevProps, nextProps) =>
+ prevProps.displayAsGroup === nextProps.displayAsGroup &&
+ prevProps.draftMessage === nextProps.draftMessage &&
+ prevProps.isMostRecentIOUReportAction !== nextProps.isMostRecentIOUReportAction &&
+ prevProps.hasOutstandingIOU === nextProps.hasOutstandingIOU &&
+ prevProps.shouldDisplayNewMarker === nextProps.shouldDisplayNewMarker &&
+ !_.isEqual(prevProps.action, nextProps.action) &&
+ lodashGet(prevProps.report, 'statusNum') === lodashGet(nextProps.report, 'statusNum') &&
+ lodashGet(prevProps.report, 'stateNum') === lodashGet(nextProps.report, 'stateNum') &&
+ prevProps.translate === nextProps.translate,
+ ),
+);
diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js
index 7b87b2aad31a..214eff33844e 100644
--- a/src/pages/home/report/ReportActionItemMessageEdit.js
+++ b/src/pages/home/report/ReportActionItemMessageEdit.js
@@ -30,6 +30,7 @@ import CONST from '../../../CONST';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
import withKeyboardState, {keyboardStatePropTypes} from '../../../components/withKeyboardState';
+import refPropTypes from '../../../components/refPropTypes';
import * as ComposerUtils from '../../../libs/ComposerUtils';
import * as ComposerActions from '../../../libs/actions/Composer';
import * as User from '../../../libs/actions/User';
@@ -48,7 +49,7 @@ const propTypes = {
index: PropTypes.number.isRequired,
/** A ref to forward to the text input */
- forwardedRef: PropTypes.func,
+ forwardedRef: refPropTypes,
/** The report currently being looked at */
// eslint-disable-next-line react/no-unused-prop-types
@@ -299,7 +300,7 @@ class ReportActionItemMessageEdit extends React.Component {
multiline
ref={(el) => {
this.textInput = el;
- this.props.forwardedRef(el);
+ this.props.forwardedRef.current = el;
}}
nativeID={this.messageEditInput}
onChangeText={this.updateDraft} // Debounced saveDraftComment
diff --git a/src/styles/getTooltipStyles.js b/src/styles/getTooltipStyles.js
index 822b0318e39a..ab2b6b433224 100644
--- a/src/styles/getTooltipStyles.js
+++ b/src/styles/getTooltipStyles.js
@@ -65,9 +65,10 @@ function isOverlappingAtTop(xOffset, yOffset, tooltip) {
}
const element = document.elementFromPoint(xOffset, yOffset);
+ const tooltipRef = (tooltip && tooltip.current) || tooltip;
// Ensure it's not the already rendered element of this very tooltip, so the tooltip doesn't try to "avoid" itself
- if (!element || (tooltip && tooltip.contains(element))) {
+ if (!element || (tooltipRef && tooltipRef.contains(element))) {
return false;
}