diff --git a/.eslintrc.js b/.eslintrc.js
index b5b4add538f6..afcea91acc34 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -37,9 +37,11 @@ module.exports = {
overrides: [
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
+ plugins: ['react'],
rules: {
'rulesdir/onyx-props-must-have-default': 'off',
'react-native-a11y/has-accessibility-hint': ['off'],
+ 'react/jsx-no-constructed-context-values': 'error',
'react-native-a11y/has-valid-accessibility-descriptors': [
'error',
{
diff --git a/src/components/AnimatedStep/AnimatedStepProvider.js b/src/components/AnimatedStep/AnimatedStepProvider.js
index 280fbd1a2776..86d40b5bddeb 100644
--- a/src/components/AnimatedStep/AnimatedStepProvider.js
+++ b/src/components/AnimatedStep/AnimatedStepProvider.js
@@ -1,4 +1,4 @@
-import React, {useState} from 'react';
+import React, {useMemo, useState} from 'react';
import PropTypes from 'prop-types';
import AnimatedStepContext from './AnimatedStepContext';
import CONST from '../../CONST';
@@ -9,8 +9,9 @@ const propTypes = {
function AnimatedStepProvider({children}) {
const [animationDirection, setAnimationDirection] = useState(CONST.ANIMATION_DIRECTION.IN);
+ const contextValue = useMemo(() => ({animationDirection, setAnimationDirection}), [animationDirection, setAnimationDirection]);
- return {children};
+ return {children};
}
AnimatedStepProvider.propTypes = propTypes;
diff --git a/src/components/Attachments/AttachmentCarousel/Pager/index.js b/src/components/Attachments/AttachmentCarousel/Pager/index.js
index 9779963dfc4a..4ca4e77e5136 100644
--- a/src/components/Attachments/AttachmentCarousel/Pager/index.js
+++ b/src/components/Attachments/AttachmentCarousel/Pager/index.js
@@ -1,5 +1,5 @@
/* eslint-disable es/no-optional-chaining */
-import React, {useRef, useState, useImperativeHandle} from 'react';
+import React, {useRef, useState, useImperativeHandle, useMemo} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import {GestureHandlerRootView, createNativeWrapper} from 'react-native-gesture-handler';
@@ -126,21 +126,34 @@ function AttachmentCarouselPager({
scrollEnabled: shouldPagerScroll.value,
}));
+ const contextValue = useMemo(() => ({
+ canvasWidth: containerWidth,
+ canvasHeight: containerHeight,
+ isScrolling,
+ pagerRef,
+ shouldPagerScroll,
+ onPinchGestureChange,
+ onTap,
+ onSwipe,
+ onSwipeSuccess,
+ onSwipeDown,
+ }), [
+ containerWidth,
+ containerHeight,
+ isScrolling,
+ pagerRef,
+ shouldPagerScroll,
+ onPinchGestureChange,
+ onTap,
+ onSwipe,
+ onSwipeSuccess,
+ onSwipeDown,
+ ]);
+
return (
({isDraggingOver, setOnDropHandler, dropZoneID: dropZoneID.current}), [isDraggingOver, setOnDropHandler]);
return (
-
+
(dropZone.current = e)}
style={[styles.flex1, styles.w100, styles.h100]}
diff --git a/src/components/PopoverProvider/index.js b/src/components/PopoverProvider/index.js
index efa230d920d5..c0c62cb70cb2 100644
--- a/src/components/PopoverProvider/index.js
+++ b/src/components/PopoverProvider/index.js
@@ -111,15 +111,15 @@ function PopoverContextProvider(props) {
[closePopover],
);
+ const contextValue = React.useMemo(() => ({
+ onOpen,
+ close: closePopover,
+ popover: activePopoverRef.current,
+ isOpen,
+ }), [onOpen, closePopover, isOpen]);
+
return (
-
+
{props.children}
);
diff --git a/src/components/PopoverProvider/index.native.js b/src/components/PopoverProvider/index.native.js
index f34abcb1fa62..aa22bc7cd605 100644
--- a/src/components/PopoverProvider/index.native.js
+++ b/src/components/PopoverProvider/index.native.js
@@ -15,15 +15,15 @@ const PopoverContext = React.createContext({
});
function PopoverContextProvider(props) {
+ const contextValue = React.useMemo(() => ({
+ onOpen: () => {},
+ close: () => {},
+ popover: {},
+ isOpen: false,
+ }), []);
+
return (
- {},
- close: () => {},
- popover: {},
- isOpen: false,
- }}
- >
+
{props.children}
);
diff --git a/src/components/ScrollViewWithContext.js b/src/components/ScrollViewWithContext.js
index bf0e7c6d62e8..b858f741f1fe 100644
--- a/src/components/ScrollViewWithContext.js
+++ b/src/components/ScrollViewWithContext.js
@@ -1,4 +1,4 @@
-import React, {useState, useRef} from 'react';
+import React, {useState, useRef, useMemo} from 'react';
import {ScrollView} from 'react-native';
const MIN_SMOOTH_SCROLL_EVENT_THROTTLE = 16;
@@ -27,6 +27,11 @@ function ScrollViewWithContext({onScroll, scrollEventThrottle, children, innerRe
setContentOffsetY(event.nativeEvent.contentOffset.y);
};
+ const contextValue = useMemo(() => ({
+ scrollViewRef,
+ contentOffsetY,
+ }), [scrollViewRef, contentOffsetY]);
+
return (
{children}
diff --git a/src/components/withKeyboardState.js b/src/components/withKeyboardState.js
index 8ddf667b4e30..dbd90af19b03 100755
--- a/src/components/withKeyboardState.js
+++ b/src/components/withKeyboardState.js
@@ -1,4 +1,4 @@
-import React, {forwardRef, createContext, useEffect, useState} from 'react';
+import React, {forwardRef, createContext, useEffect, useState, useMemo} from 'react';
import {Keyboard} from 'react-native';
import PropTypes from 'prop-types';
import getComponentDisplayName from '../libs/getComponentDisplayName';
@@ -31,7 +31,10 @@ function KeyboardStateProvider(props) {
};
}, []);
- return {children};
+ const contextValue = useMemo(() => ({
+ isKeyboardShown,
+ }), [isKeyboardShown]);
+ return {children};
}
KeyboardStateProvider.propTypes = keyboardStateProviderPropTypes;
diff --git a/src/components/withWindowDimensions/index.js b/src/components/withWindowDimensions/index.js
index 37d5c94688a2..bd08fb673c2a 100644
--- a/src/components/withWindowDimensions/index.js
+++ b/src/components/withWindowDimensions/index.js
@@ -1,8 +1,8 @@
-import React, {forwardRef, createContext, useState, useEffect} from 'react';
+import React, {forwardRef, createContext, useState, useEffect, useMemo} from 'react';
import PropTypes from 'prop-types';
import lodashDebounce from 'lodash/debounce';
import {Dimensions} from 'react-native';
-import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
+import {useSafeAreaInsets} from 'react-native-safe-area-context';
import getComponentDisplayName from '../../libs/getComponentDisplayName';
import variables from '../../styles/variables';
import getWindowHeightAdjustment from '../../libs/getWindowHeightAdjustment';
@@ -62,30 +62,28 @@ function WindowDimensionsProvider(props) {
dimensionsEventListener.remove();
};
}, []);
-
+ const insets = useSafeAreaInsets();
+ const adjustment = getWindowHeightAdjustment(insets);
+ const contextValue = useMemo(() => {
+ const isExtraSmallScreenWidth = windowDimension.windowWidth <= variables.extraSmallMobileResponsiveWidthBreakpoint;
+ const isSmallScreenWidth = windowDimension.windowWidth <= variables.mobileResponsiveWidthBreakpoint;
+ const isMediumScreenWidth = !isSmallScreenWidth && windowDimension.windowWidth <= variables.tabletResponsiveWidthBreakpoint;
+ const isLargeScreenWidth = !isSmallScreenWidth && !isMediumScreenWidth;
+ return {
+ windowHeight: windowDimension.windowHeight + adjustment,
+ windowWidth: windowDimension.windowWidth,
+ isExtraSmallScreenWidth,
+ isSmallScreenWidth,
+ isMediumScreenWidth,
+ isLargeScreenWidth,
+ };
+ }, [windowDimension.windowHeight, windowDimension.windowWidth, adjustment]);
return (
-
- {(insets) => {
- const isExtraSmallScreenWidth = windowDimension.windowWidth <= variables.extraSmallMobileResponsiveWidthBreakpoint;
- const isSmallScreenWidth = windowDimension.windowWidth <= variables.mobileResponsiveWidthBreakpoint;
- const isMediumScreenWidth = !isSmallScreenWidth && windowDimension.windowWidth <= variables.tabletResponsiveWidthBreakpoint;
- const isLargeScreenWidth = !isSmallScreenWidth && !isMediumScreenWidth;
- return (
-
- {props.children}
-
- );
- }}
-
+
+ {props.children}
+
);
}
diff --git a/src/components/withWindowDimensions/index.native.js b/src/components/withWindowDimensions/index.native.js
index e147a20c9f4e..bd0b6574ddf4 100644
--- a/src/components/withWindowDimensions/index.native.js
+++ b/src/components/withWindowDimensions/index.native.js
@@ -1,7 +1,7 @@
-import React, {forwardRef, createContext, useState, useEffect} from 'react';
+import React, {forwardRef, createContext, useState, useEffect, useMemo} from 'react';
import PropTypes from 'prop-types';
import {Dimensions} from 'react-native';
-import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
+import {useSafeAreaInsets} from 'react-native-safe-area-context';
import getComponentDisplayName from '../../libs/getComponentDisplayName';
import variables from '../../styles/variables';
import getWindowHeightAdjustment from '../../libs/getWindowHeightAdjustment';
@@ -60,30 +60,25 @@ function WindowDimensionsProvider(props) {
dimensionsEventListener.remove();
};
}, []);
-
+ const insets = useSafeAreaInsets();
+ const adjustment = getWindowHeightAdjustment(insets);
+ const contextValue = useMemo(() => {
+ const isExtraSmallScreenWidth = windowDimension.windowWidth <= variables.extraSmallMobileResponsiveWidthBreakpoint;
+ return {
+ windowHeight: windowDimension.windowHeight + adjustment,
+ windowWidth: windowDimension.windowWidth,
+ isExtraSmallScreenWidth,
+ isSmallScreenWidth: true,
+ isMediumScreenWidth: false,
+ isLargeScreenWidth: false,
+ };
+ }, [windowDimension.windowHeight, windowDimension.windowWidth, adjustment]);
return (
-
- {(insets) => {
- const isExtraSmallScreenWidth = windowDimension.windowWidth <= variables.extraSmallMobileResponsiveWidthBreakpoint;
- const isSmallScreenWidth = true;
- const isMediumScreenWidth = false;
- const isLargeScreenWidth = false;
- return (
-
- {props.children}
-
- );
- }}
-
+
+ {props.children}
+
);
}
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index d109c972ec69..ecaa8c0a84d4 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, {useState, useRef, useEffect, memo, useCallback, useContext} from 'react';
+import React, {useState, useRef, useEffect, memo, useCallback, useContext, useMemo} from 'react';
import {InteractionManager, View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
@@ -263,6 +263,13 @@ function ReportActionItem(props) {
[props.report, props.action, props.emojiReactions],
);
+ const contextValue = useMemo(() => ({
+ anchor: popoverAnchorRef,
+ report: props.report,
+ action: props.action,
+ checkIfContextMenuActive: toggleContextMenuFromActiveReportAction,
+ }), [props.report, props.action, toggleContextMenuFromActiveReportAction]);
+
/**
* Get the content of ReportActionItem
* @param {Boolean} hovered whether the ReportActionItem is hovered
@@ -356,12 +363,7 @@ function ReportActionItem(props) {
const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision);
children = (
{!props.draftMessage ? (
@@ -504,12 +506,7 @@ function ReportActionItem(props) {
if (ReportActionsUtils.isTransactionThread(parentReportAction)) {
return (
({setStep: handleSetStep}), [handleSetStep]);
const renderStep = () => {
switch (currentStep) {
@@ -60,9 +61,7 @@ function TwoFactorAuthSteps({account = defaultAccount}) {
return (
{renderStep()}