Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 24 additions & 56 deletions src/base/Hidden/Hidden.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMediaQuery, useTheme } from '@mui/material';
import React from 'react';
import React, { useMemo } from 'react';

type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';

Expand All @@ -16,9 +16,13 @@ export interface HiddenProps {
mdDown?: boolean;
lgDown?: boolean;
xlDown?: boolean;

}

const BREAKPOINTS: Breakpoint[] = ['xs', 'sm', 'md', 'lg', 'xl'];

const extractCondition = (mediaQuery: string) =>
mediaQuery.replace(/^@media\s*/i, '');

export const Hidden = ({
children,
only,
Expand All @@ -34,63 +38,27 @@ export const Hidden = ({
xlDown = false
}: HiddenProps) => {
const theme = useTheme();
const onlyValues = Array.isArray(only) ? only : only ? [only] : [];

const conditions: string[] = [];
const mediaQuery = useMemo(() => {
const onlyValues = Array.isArray(only) ? only : only ? [only] : [];
const upProps: Record<Breakpoint, boolean> = { xs: xsUp, sm: smUp, md: mdUp, lg: lgUp, xl: xlUp };
const downProps: Record<Breakpoint, boolean> = { xs: xsDown, sm: smDown, md: mdDown, lg: lgDown, xl: xlDown };
const conditions: string[] = [];

const extractCondition = (mediaQuery: string) =>
mediaQuery.replace(/^@media\s*/i, '');

if (onlyValues.includes('xs')) {
conditions.push(extractCondition(theme.breakpoints.only('xs')));
}
if (onlyValues.includes('sm')) {
conditions.push(extractCondition(theme.breakpoints.only('sm')));
}
if (onlyValues.includes('md')) {
conditions.push(extractCondition(theme.breakpoints.only('md')));
}
if (onlyValues.includes('lg')) {
conditions.push(extractCondition(theme.breakpoints.only('lg')));
}
if (onlyValues.includes('xl')) {
conditions.push(extractCondition(theme.breakpoints.only('xl')));
}

if (xsUp) {
conditions.push(extractCondition(theme.breakpoints.up('xs')));
}
if (smUp) {
conditions.push(extractCondition(theme.breakpoints.up('sm')));
}
if (mdUp) {
conditions.push(extractCondition(theme.breakpoints.up('md')));
}
if (lgUp) {
conditions.push(extractCondition(theme.breakpoints.up('lg')));
}
if (xlUp) {
conditions.push(extractCondition(theme.breakpoints.up('xl')));
}

if (xsDown) {
conditions.push(extractCondition(theme.breakpoints.down('xs')));
}
if (smDown) {
conditions.push(extractCondition(theme.breakpoints.down('sm')));
}
if (mdDown) {
conditions.push(extractCondition(theme.breakpoints.down('md')));
}
if (lgDown) {
conditions.push(extractCondition(theme.breakpoints.down('lg')));
}
if (xlDown) {
conditions.push(extractCondition(theme.breakpoints.down('xl')));
}
for (const bp of BREAKPOINTS) {
if (onlyValues.includes(bp)) {
conditions.push(extractCondition(theme.breakpoints.only(bp)));
}
if (upProps[bp]) {
conditions.push(extractCondition(theme.breakpoints.up(bp)));
}
if (downProps[bp]) {
conditions.push(extractCondition(theme.breakpoints.down(bp)));
}
}

const mediaQuery =
conditions.length > 0 ? `@media ${conditions.join(', ')}` : '@media not all';
return conditions.length > 0 ? `@media ${conditions.join(', ')}` : '@media not all';
}, [only, xsUp, smUp, mdUp, lgUp, xlUp, xsDown, smDown, mdDown, lgDown, xlDown, theme.breakpoints]);
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When only is passed as an array literal (e.g., only={['xs', 'md']}), which is the typical usage pattern, a new array reference is created on every parent render. Since only is used directly as a useMemo dependency, this causes the memo to recompute on every render, defeating the purpose of the memoization.

Consider spreading the array into the dependency list (e.g., using JSON.stringify(only) or only?.toString() as the dependency), or converting only to a stable representation before using it as a dependency.

Copilot uses AI. Check for mistakes.

const matches = useMediaQuery(mediaQuery);

Expand Down