diff --git a/docs/data/base/components/menu/UseMenu.js b/docs/data/base/components/menu/UseMenu.js
index d495d627a0b845..df277a54b158fc 100644
--- a/docs/data/base/components/menu/UseMenu.js
+++ b/docs/data/base/components/menu/UseMenu.js
@@ -150,13 +150,16 @@ const Menu = React.forwardRef(function Menu(props, ref) {
open,
});
- const contextValue = {
- registerItem,
- unregisterItem,
- getItemState,
- getItemProps,
- open: true,
- };
+ const contextValue = React.useMemo(
+ () => ({
+ registerItem,
+ unregisterItem,
+ getItemState,
+ getItemProps,
+ open: true,
+ }),
+ [getItemProps, getItemState, registerItem, unregisterItem],
+ );
return (
diff --git a/docs/data/base/components/menu/UseMenu.tsx b/docs/data/base/components/menu/UseMenu.tsx
index 62021d9b0835a1..dd693e238d9163 100644
--- a/docs/data/base/components/menu/UseMenu.tsx
+++ b/docs/data/base/components/menu/UseMenu.tsx
@@ -159,13 +159,16 @@ const Menu = React.forwardRef(function Menu(
open,
});
- const contextValue: MenuUnstyledContextType = {
- registerItem,
- unregisterItem,
- getItemState,
- getItemProps,
- open: true,
- };
+ const contextValue: MenuUnstyledContextType = React.useMemo(
+ () => ({
+ registerItem,
+ unregisterItem,
+ getItemState,
+ getItemProps,
+ open: true,
+ }),
+ [getItemProps, getItemState, registerItem, unregisterItem],
+ );
return (
diff --git a/docs/pages/_app.js b/docs/pages/_app.js
index 153b9a2eea1a30..f15d0113ea677f 100644
--- a/docs/pages/_app.js
+++ b/docs/pages/_app.js
@@ -167,6 +167,11 @@ function AppWrapper(props) {
];
}
+ const pageContextValue = React.useMemo(
+ () => ({ activePage, pages: productPages }),
+ [activePage, productPages],
+ );
+
return (
@@ -178,7 +183,7 @@ function AppWrapper(props) {
-
+
{children}
diff --git a/examples/remix-with-typescript/app/entry.client.tsx b/examples/remix-with-typescript/app/entry.client.tsx
index 08729b40d45dc7..a2e76d63c4f66e 100644
--- a/examples/remix-with-typescript/app/entry.client.tsx
+++ b/examples/remix-with-typescript/app/entry.client.tsx
@@ -15,12 +15,17 @@ interface ClientCacheProviderProps {
function ClientCacheProvider({ children }: ClientCacheProviderProps) {
const [cache, setCache] = useState(createEmotionCache());
- function reset() {
- setCache(createEmotionCache());
- }
+ const clientStyleContextValue = React.useMemo(
+ () => ({
+ reset() {
+ setCache(createEmotionCache());
+ },
+ }),
+ [],
+ );
return (
-
+
{children}
);
diff --git a/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.tsx b/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.tsx
index a905ae08a1991c..cef6cac4b0e5e1 100644
--- a/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.tsx
+++ b/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.tsx
@@ -108,26 +108,26 @@ const FormControlUnstyled = React.forwardRef(function FormControlUnstyled<
required,
};
- const handleChange = (event: React.ChangeEvent) => {
- setValue(event.target.value);
- onChange?.(event);
- };
-
- const childContext: FormControlUnstyledState = {
- disabled,
- error,
- filled,
- focused,
- onBlur: () => {
- setFocused(false);
- },
- onChange: handleChange,
- onFocus: () => {
- setFocused(true);
- },
- required,
- value: value ?? '',
- };
+ const childContext: FormControlUnstyledState = React.useMemo(() => {
+ return {
+ disabled,
+ error,
+ filled,
+ focused,
+ onBlur: () => {
+ setFocused(false);
+ },
+ onChange: (event: React.ChangeEvent) => {
+ setValue(event.target.value);
+ onChange?.(event);
+ },
+ onFocus: () => {
+ setFocused(true);
+ },
+ required,
+ value: value ?? '',
+ };
+ }, [disabled, error, filled, focused, onChange, required, setValue, value]);
const classes = useUtilityClasses(ownerState);
diff --git a/packages/mui-base/src/MenuUnstyled/MenuUnstyled.tsx b/packages/mui-base/src/MenuUnstyled/MenuUnstyled.tsx
index 1abbc8d0460e2e..24efe56b16072e 100644
--- a/packages/mui-base/src/MenuUnstyled/MenuUnstyled.tsx
+++ b/packages/mui-base/src/MenuUnstyled/MenuUnstyled.tsx
@@ -106,13 +106,16 @@ const MenuUnstyled = React.forwardRef(function MenuUnstyled<
className: classes.listbox,
});
- const contextValue: MenuUnstyledContextType = {
- registerItem,
- unregisterItem,
- getItemState,
- getItemProps,
- open,
- };
+ const contextValue: MenuUnstyledContextType = React.useMemo(
+ () => ({
+ registerItem,
+ unregisterItem,
+ getItemState,
+ getItemProps,
+ open,
+ }),
+ [getItemProps, getItemState, open, registerItem, unregisterItem],
+ );
return (
diff --git a/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.tsx b/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.tsx
index 8b669dfda2a197..5b8eb0d250e252 100644
--- a/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.tsx
+++ b/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.tsx
@@ -219,11 +219,14 @@ const MultiSelectUnstyled = React.forwardRef(function MultiSelectUnstyled ({
+ getOptionProps,
+ getOptionState,
+ listboxRef,
+ }),
+ [getOptionProps, getOptionState],
+ );
return (
diff --git a/packages/mui-base/src/SelectUnstyled/SelectUnstyled.tsx b/packages/mui-base/src/SelectUnstyled/SelectUnstyled.tsx
index b42399c813f3d5..a89a8865ac5b0a 100644
--- a/packages/mui-base/src/SelectUnstyled/SelectUnstyled.tsx
+++ b/packages/mui-base/src/SelectUnstyled/SelectUnstyled.tsx
@@ -208,11 +208,14 @@ const SelectUnstyled = React.forwardRef(function SelectUnstyled ({
+ getOptionProps,
+ getOptionState,
+ listboxRef,
+ }),
+ [getOptionProps, getOptionState],
+ );
return (
diff --git a/packages/mui-joy/src/AvatarGroup/AvatarGroup.tsx b/packages/mui-joy/src/AvatarGroup/AvatarGroup.tsx
index 6b5b379c93d218..15905d00e943c1 100644
--- a/packages/mui-joy/src/AvatarGroup/AvatarGroup.tsx
+++ b/packages/mui-joy/src/AvatarGroup/AvatarGroup.tsx
@@ -49,13 +49,16 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(inProps, ref) {
const { className, color, component = 'div', size = 'md', variant, children, ...other } = props;
- const ownerState = {
- ...props,
- color,
- component,
- size,
- variant,
- };
+ const ownerState = React.useMemo(
+ () => ({
+ ...props,
+ color,
+ component,
+ size,
+ variant,
+ }),
+ [color, component, props, size, variant],
+ );
const classes = useUtilityClasses();
diff --git a/packages/mui-joy/src/Chip/Chip.tsx b/packages/mui-joy/src/Chip/Chip.tsx
index ca493fa7cf3a2a..9a58948fca42c8 100644
--- a/packages/mui-joy/src/Chip/Chip.tsx
+++ b/packages/mui-joy/src/Chip/Chip.tsx
@@ -275,8 +275,13 @@ const Chip = React.forwardRef(function Chip(inProps, ref) {
className: classes.endDecorator,
});
+ const chipContextValue = React.useMemo(
+ () => ({ disabled, variant, color }),
+ [color, disabled, variant],
+ );
+
return (
-
+
(null);
const ownerState = {
@@ -117,21 +115,24 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) {
const classes = useUtilityClasses(ownerState);
+ const formControlContextValue = React.useMemo(
+ () => ({
+ disabled,
+ required,
+ error,
+ color,
+ size,
+ htmlFor: id,
+ labelId: `${id}-label`,
+ 'aria-describedby': helperText ? `${id}-helper-text` : undefined,
+ setHelperText,
+ registerEffect: registerEffect!,
+ }),
+ [color, disabled, error, helperText, id, registerEffect, required, size],
+ );
+
return (
-
+
({
+ registerItem,
+ unregisterItem,
+ getItemState,
+ getItemProps,
+ open,
+ }),
+ [getItemProps, getItemState, open, registerItem, unregisterItem],
+ );
return (
diff --git a/packages/mui-joy/src/MenuList/MenuList.tsx b/packages/mui-joy/src/MenuList/MenuList.tsx
index e656ced8679774..f1f06d1dc21b53 100644
--- a/packages/mui-joy/src/MenuList/MenuList.tsx
+++ b/packages/mui-joy/src/MenuList/MenuList.tsx
@@ -109,14 +109,18 @@ const MenuList = React.forwardRef(function MenuList(inProps, ref) {
className: classes.root,
});
- const contextValue = {
- registerItem,
- unregisterItem,
- getItemState,
- getItemProps,
- getListboxProps,
- open: true,
- } as MenuUnstyledContextType;
+ const contextValue = React.useMemo(
+ () =>
+ ({
+ registerItem,
+ unregisterItem,
+ getItemState,
+ getItemProps,
+ getListboxProps,
+ open: true,
+ } as MenuUnstyledContextType),
+ [getItemProps, getItemState, getListboxProps, registerItem, unregisterItem],
+ );
return (
diff --git a/packages/mui-joy/src/ModalDialog/ModalDialog.tsx b/packages/mui-joy/src/ModalDialog/ModalDialog.tsx
index efec43c81f96e5..7542cc2b4c3021 100644
--- a/packages/mui-joy/src/ModalDialog/ModalDialog.tsx
+++ b/packages/mui-joy/src/ModalDialog/ModalDialog.tsx
@@ -109,9 +109,11 @@ const ModalDialog = React.forwardRef(function ModalDialog(inProps, ref) {
const classes = useUtilityClasses(ownerState);
+ const contextValue = React.useMemo(() => ({ variant, color }), [color, variant]);
+
return (
-
+
) => {
- setValueState(event.target.value);
-
- if (onChange) {
- onChange(event);
- }
- };
-
const name = useId(nameProp);
const formControl = React.useContext(FormControlContext);
@@ -114,18 +106,27 @@ const RadioGroup = React.forwardRef(function RadioGroup(inProps, ref) {
}, [registerEffect]);
}
+ const contextValue = React.useMemo(
+ () => ({
+ disableIcon,
+ overlay,
+ row,
+ size,
+ name,
+ value,
+ onChange: (event: React.ChangeEvent) => {
+ setValueState(event.target.value);
+
+ if (onChange) {
+ onChange(event);
+ }
+ },
+ }),
+ [disableIcon, name, onChange, overlay, row, setValueState, size, value],
+ );
+
return (
-
+
(
className: classes.indicator,
});
- const context = {
- getOptionProps,
- getOptionState,
- listboxRef,
- color,
- };
+ const context = React.useMemo(
+ () => ({
+ getOptionProps,
+ getOptionState,
+ listboxRef,
+ color,
+ }),
+ [color, getOptionProps, getOptionState],
+ );
return (
diff --git a/packages/mui-lab/src/Timeline/Timeline.tsx b/packages/mui-lab/src/Timeline/Timeline.tsx
index 874ad17cbde2fb..2baa6ffc8d9813 100644
--- a/packages/mui-lab/src/Timeline/Timeline.tsx
+++ b/packages/mui-lab/src/Timeline/Timeline.tsx
@@ -91,8 +91,11 @@ const Timeline = React.forwardRef(function Time
const { position = 'right', className, ...other } = props;
const ownerState = { ...props, position };
const classes = useUtilityClasses(ownerState);
+
+ const contextValue = React.useMemo(() => ({ position }), [position]);
+
return (
-
+
({ position: ownerState.position }),
+ [ownerState.position],
+ );
+
return (
-
+
{
- setFilled(true);
- }, []);
-
- const onEmpty = React.useCallback(() => {
- setFilled(false);
- }, []);
-
- const childContext = {
+ const childContext = React.useMemo(() => {
+ return {
+ adornedStart,
+ setAdornedStart,
+ color,
+ disabled,
+ error,
+ filled,
+ focused,
+ fullWidth,
+ hiddenLabel,
+ size,
+ onBlur: () => {
+ setFocused(false);
+ },
+ onEmpty: () => {
+ setFilled(false);
+ },
+ onFilled: () => {
+ setFilled(true);
+ },
+ onFocus: () => {
+ setFocused(true);
+ },
+ registerEffect,
+ required,
+ variant,
+ };
+ }, [
adornedStart,
- setAdornedStart,
color,
disabled,
error,
@@ -198,19 +217,11 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) {
focused,
fullWidth,
hiddenLabel,
- size,
- onBlur: () => {
- setFocused(false);
- },
- onEmpty,
- onFilled,
- onFocus: () => {
- setFocused(true);
- },
registerEffect,
required,
+ size,
variant,
- };
+ ]);
return (
diff --git a/packages/mui-material/src/ListItem/ListItem.js b/packages/mui-material/src/ListItem/ListItem.js
index 4a72d51dcee0d4..0ca2b36bd1c656 100644
--- a/packages/mui-material/src/ListItem/ListItem.js
+++ b/packages/mui-material/src/ListItem/ListItem.js
@@ -194,11 +194,14 @@ const ListItem = React.forwardRef(function ListItem(inProps, ref) {
} = props;
const context = React.useContext(ListContext);
- const childContext = {
- dense: dense || context.dense || false,
- alignItems,
- disableGutters,
- };
+ const childContext = React.useMemo(
+ () => ({
+ dense: dense || context.dense || false,
+ alignItems,
+ disableGutters,
+ }),
+ [alignItems, context.dense, dense, disableGutters],
+ );
const listItemRef = React.useRef(null);
useEnhancedEffect(() => {
diff --git a/packages/mui-material/src/ListItemButton/ListItemButton.js b/packages/mui-material/src/ListItemButton/ListItemButton.js
index 33eb723f5d8094..aecdb0ca25fbcf 100644
--- a/packages/mui-material/src/ListItemButton/ListItemButton.js
+++ b/packages/mui-material/src/ListItemButton/ListItemButton.js
@@ -141,11 +141,14 @@ const ListItemButton = React.forwardRef(function ListItemButton(inProps, ref) {
} = props;
const context = React.useContext(ListContext);
- const childContext = {
- dense: dense || context.dense || false,
- alignItems,
- disableGutters,
- };
+ const childContext = React.useMemo(
+ () => ({
+ dense: dense || context.dense || false,
+ alignItems,
+ disableGutters,
+ }),
+ [alignItems, context.dense, dense, disableGutters],
+ );
const listItemRef = React.useRef(null);
useEnhancedEffect(() => {
diff --git a/packages/mui-material/src/MenuItem/MenuItem.js b/packages/mui-material/src/MenuItem/MenuItem.js
index 82a54d493354fc..f574398a4dc6a7 100644
--- a/packages/mui-material/src/MenuItem/MenuItem.js
+++ b/packages/mui-material/src/MenuItem/MenuItem.js
@@ -161,10 +161,13 @@ const MenuItem = React.forwardRef(function MenuItem(inProps, ref) {
} = props;
const context = React.useContext(ListContext);
- const childContext = {
- dense: dense || context.dense || false,
- disableGutters,
- };
+ const childContext = React.useMemo(
+ () => ({
+ dense: dense || context.dense || false,
+ disableGutters,
+ }),
+ [context.dense, dense, disableGutters],
+ );
const menuItemRef = React.useRef(null);
useEnhancedEffect(() => {
diff --git a/packages/mui-material/src/RadioGroup/RadioGroup.js b/packages/mui-material/src/RadioGroup/RadioGroup.js
index fea89c9dfb81f3..ff90acdb44daf0 100644
--- a/packages/mui-material/src/RadioGroup/RadioGroup.js
+++ b/packages/mui-material/src/RadioGroup/RadioGroup.js
@@ -46,18 +46,25 @@ const RadioGroup = React.forwardRef(function RadioGroup(props, ref) {
const handleRef = useForkRef(ref, rootRef);
- const handleChange = (event) => {
- setValueState(event.target.value);
+ const name = useId(nameProp);
- if (onChange) {
- onChange(event, event.target.value);
- }
- };
+ const contextValue = React.useMemo(
+ () => ({
+ name,
+ onChange(event) {
+ setValueState(event.target.value);
- const name = useId(nameProp);
+ if (onChange) {
+ onChange(event, event.target.value);
+ }
+ },
+ value,
+ }),
+ [name, onChange, setValueState, value],
+ );
return (
-
+
{children}
diff --git a/packages/mui-system/src/ThemeProvider/ThemeProvider.js b/packages/mui-system/src/ThemeProvider/ThemeProvider.js
index d5249b2e6fdbbd..6f5409040753f2 100644
--- a/packages/mui-system/src/ThemeProvider/ThemeProvider.js
+++ b/packages/mui-system/src/ThemeProvider/ThemeProvider.js
@@ -5,10 +5,12 @@ import { exactProp } from '@mui/utils';
import { ThemeContext as StyledEngineThemeContext } from '@mui/styled-engine';
import useTheme from '../useTheme';
+const EMPTY_THEME = {};
+
function InnerThemeProvider(props) {
const theme = useTheme();
return (
-
+
{props.children}
);
diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.js b/packages/mui-system/src/cssVars/createCssVarsProvider.js
index a867989af5e2e7..933e0e907926c7 100644
--- a/packages/mui-system/src/cssVars/createCssVarsProvider.js
+++ b/packages/mui-system/src/cssVars/createCssVarsProvider.js
@@ -216,19 +216,31 @@ export default function createCssVarsProvider(options) {
};
}, []);
+ const contextValue = React.useMemo(
+ () => ({
+ mode,
+ systemMode,
+ setMode,
+ lightColorScheme,
+ darkColorScheme,
+ colorScheme,
+ setColorScheme,
+ allColorSchemes,
+ }),
+ [
+ allColorSchemes,
+ colorScheme,
+ darkColorScheme,
+ lightColorScheme,
+ mode,
+ setColorScheme,
+ setMode,
+ systemMode,
+ ],
+ );
+
return (
-
+