diff --git a/.eslintrc.js b/.eslintrc.js
index 75a74ed371c4..78683b043f50 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -37,10 +37,12 @@ module.exports = {
overrides: [
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
+ plugins: ['react'],
rules: {
'rulesdir/no-multiple-onyx-in-file': 'off',
'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..d10a5abad6b7 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,22 +126,25 @@ 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..15ad5da74595 100644
--- a/src/components/PopoverProvider/index.js
+++ b/src/components/PopoverProvider/index.js
@@ -111,18 +111,17 @@ function PopoverContextProvider(props) {
[closePopover],
);
- return (
-
- {props.children}
-
+ const contextValue = React.useMemo(
+ () => ({
+ onOpen,
+ close: closePopover,
+ popover: activePopoverRef.current,
+ isOpen,
+ }),
+ [onOpen, closePopover, isOpen],
);
+
+ return {props.children};
}
PopoverContextProvider.defaultProps = defaultProps;
diff --git a/src/components/PopoverProvider/index.native.js b/src/components/PopoverProvider/index.native.js
index f34abcb1fa62..e4da13752b6d 100644
--- a/src/components/PopoverProvider/index.native.js
+++ b/src/components/PopoverProvider/index.native.js
@@ -15,18 +15,17 @@ const PopoverContext = React.createContext({
});
function PopoverContextProvider(props) {
- return (
- {},
- close: () => {},
- popover: {},
- isOpen: false,
- }}
- >
- {props.children}
-
+ const contextValue = React.useMemo(
+ () => ({
+ onOpen: () => {},
+ close: () => {},
+ popover: {},
+ isOpen: false,
+ }),
+ [],
);
+
+ return {props.children};
}
PopoverContextProvider.defaultProps = defaultProps;
diff --git a/src/components/ScrollViewWithContext.js b/src/components/ScrollViewWithContext.js
index bf0e7c6d62e8..1d183e250767 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,14 @@ function ScrollViewWithContext({onScroll, scrollEventThrottle, children, innerRe
setContentOffsetY(event.nativeEvent.contentOffset.y);
};
+ const contextValue = useMemo(
+ () => ({
+ scrollViewRef,
+ contentOffsetY,
+ }),
+ [scrollViewRef, contentOffsetY],
+ );
+
return (
-
- {children}
-
+ {children}
);
}
diff --git a/src/components/withKeyboardState.js b/src/components/withKeyboardState.js
index 8ddf667b4e30..3154f7e98d67 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,13 @@ 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..16e5985e0985 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,31 +62,23 @@ function WindowDimensionsProvider(props) {
dimensionsEventListener.remove();
};
}, []);
-
- 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}
-
- );
- }}
-
- );
+ 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 {props.children};
}
WindowDimensionsProvider.propTypes = windowDimensionsProviderPropTypes;
diff --git a/src/components/withWindowDimensions/index.native.js b/src/components/withWindowDimensions/index.native.js
index e147a20c9f4e..363196b3fd4d 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,31 +60,20 @@ function WindowDimensionsProvider(props) {
dimensionsEventListener.remove();
};
}, []);
-
- return (
-
- {(insets) => {
- const isExtraSmallScreenWidth = windowDimension.windowWidth <= variables.extraSmallMobileResponsiveWidthBreakpoint;
- const isSmallScreenWidth = true;
- const isMediumScreenWidth = false;
- const isLargeScreenWidth = false;
- return (
-
- {props.children}
-
- );
- }}
-
- );
+ 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 {props.children};
}
WindowDimensionsProvider.propTypes = windowDimensionsProviderPropTypes;
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index d0e84499a443..db5ac43d9d34 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -274,6 +274,16 @@ 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
@@ -366,14 +376,7 @@ function ReportActionItem(props) {
} else {
const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision);
children = (
-
+
{!props.draftMessage ? (
+
({setStep: handleSetStep}), [handleSetStep]);
const renderStep = () => {
switch (currentStep) {
@@ -58,15 +59,7 @@ function TwoFactorAuthSteps({account = defaultAccount}) {
}
};
- return (
-
- {renderStep()}
-
- );
+ return {renderStep()};
}
TwoFactorAuthSteps.propTypes = TwoFactorAuthPropTypes;