React suspense wouldn't work on latest Next 12 despite configuration - reactjs

So I have this file called AuthHeader.js in which I am attempting to render children surrounded by a Suspense boundary with a fallback. I added a 5 second delay on the API hoping to see a loader, but it shows blank. I hope someone may be able to help.
I have imported it correctly below:
import { useState, Suspense } from "react";
AuthHeader.js
<Box
component="main"
sx={{
flexGrow: 1,
p: 3,
display: { xs: open ? "none" : "block", md: "block" },
}}
>
<DrawerHeader />
<Suspense fallback={<Spinner />}>
{/* A component that uses Suspense-based */}
{children}
</Suspense>
</Box>
Spinner is contained inside the AuthHeader.js component.
// create a Spinner component with a Circular spinner inside it
const Spinner = () => (
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh",
}}
>
<CircularProgress />
</Box>
);
I also have the following setup on next.config.js
module.exports = {
reactStrictMode: true,
experimental: {
concurrentFeatures: true,
},
images: {
domains: ["images.pexels.com"],
},
};

Related

React MUI Collapse component ignores timeout and acts as if timeout is 0

I'm using React, Typescript with MUI and I wanted to make a burger menu where each clicking on an option smoothly opens a <Box> component, which contains additional options. What happens is that it ignores the timeout={2000} prop and just displays it as if it's display is none and then gets turned into display:block for example.
const [badgeMenuOpen, setBadgeMenuOpen] = useState<boolean>(false);
const [badgeMenuOpen1, setBadgeMenuOpen1] = useState<boolean>(false);
const [badgeMenuOpen2, setBadgeMenuOpen2] = useState<boolean\>(false);
const handleMenuClick = () => {
if (badgeMenuOpen) {
setBadgeMenuOpen(false);
} else {
setBadgeMenuOpen(true);
}
};
const handleMenu1Click = () => {
if (badgeMenuOpen1) {
setBadgeMenuOpen1(false);
} else {
setBadgeMenuOpen1(true);
}
};
const handleMenu2Click = () => {
if (badgeMenuOpen2) {
setBadgeMenuOpen2(false);
} else {
setBadgeMenuOpen2(true);
}
};
<IconButton
size="medium"
edge="start"
sx={{ color: "#0073d1" }}
aria-label="sidebar-logo"
onClick={handleSideMenuClick}
/>
<Typography>menu\</Typography>
<MenuIcon\>
<IconButton\>
<StyledDrawer
open={sideMenuOpen}
anchor="right"
hideBackdrop={true}
aria-controls={sideMenuOpen ? "sidebar-logo" : undefined}
aria-expanded={sideMenuOpen ? true : false}
sx={{ marginTop: "60px", backgroundColor: "#f8f8f" }}
onClose={() =\> {
setSideMenuOpen(false);
}}
id="MUI-drawer"
\>
<Box minWidth={"100%"} role="presentation"\>
<List
disablePadding={true}
sx={{ minWidth: "100%", display: "flex", flexDirection: "column" }}
\>
<ListItem sx={{ display: "flex", justifyContent: "center" }}>
<RouterLink
className="header__phone-menu__item__submenu__item"
to="/home"
\>
{t("exampletext")}
</RouterLink\>
<Divider /\>
</ListItem\>
<Divider /\>
<ListItem
disablePadding={true}
sx={{
display: "flex",
flexDirection: "column",
backgroundColor: badgeMenuOpen1 ? "#fff" : "#f8f8f",
}}
\>
<StyledBadge
onClick={handleMenu1Click}
id={"badgeMenu"}
color="error"
invisible={false}
badgeContent={"!"}
sx={{
display: "flex",
flexDirection: "column",
}}
className="header__phone-menu__item__submenu-toggle"
\>
{t("exampletext")}
</StyledBadge>
<Box
sx={{ height: badgeMenuOpen1 ? "100%" : "0px" }}
id="badgeId"
className="header__phone-menu__item__submenu"
\>
<RouterLink
className="header__phone-menu__item__submenu__item"
to="/cards"
\>
{t("exampletext")}
</RouterLink\>
I tried using <Fade> component, which actually worked, but it just changed it's opacity to 0 so the space was still occupied and that doesn't quite work for me.
Are there any specific parents that the `<Collapse>` component has to be inside for it to work?
--EDIT-- Ignore the \ inside the code, stackoverflow formated it somehow

Making child element fill to the height of the parent container React MUI

I am trying to build a React Dashboard with MUI. Its with an AppBar and a drawer and the content area is a box (Please correct anything wrong box with specified spec is a perfect approach)..
But the problem I am facing is I cant make the container placeholder which is the Box itself to stretch its height to the full height of the page.
Here is my tsx
export default function RootContainer() {
const [open, setOpen] = React.useState(false);
const title="Manage Recipes";
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: 'flex-end',
}));
const drawerWidth = 240;
const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
open?: boolean;
}>(({ theme, open }) => ({
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: `-${drawerWidth}px`,
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
}),
}));
return (
<Box sx={{ display: 'flex', bgcolor:"silver",height:"100vh" }}>
<CssBaseline />
<AppBar open={open} onDrawerOpen={handleDrawerOpen} />
<Drawer open={open} onDrawerClose={handleDrawerClose} />
<Main open={open} >
<DrawerHeader />
<Container maxWidth="xl">
<h2>{title}</h2>
<Paper elevation={1} sx={{bgcolor:"#f7f9ff", height:"100%"}}>
<ManageRecipe />
</Paper>
</Container>
</Main>
</Box>
);
}
How can I achieve that to get full height (not full width)
*****Update Based on Answer
Based on the answer I have updated the page and the parent works fine now. It stretches to its full size without scroll.
But the two child elements causing some trouble as it still not full height.
So I updated the child container like this
<Container maxWidth="xl" sx={{margin:"20", bgcolor:"red", height:1}} >
<h2>{title}</h2>
<Paper elevation={1} sx={{bgcolor:"#f7f9ff", height:1/2}}>
<ManageRecipe />
</Paper>
</Container>
Now it looks like the child container bleeds out of the parent like this
I was expecting the Container stay within the parent box with a bottom padding of 20px. But it doesnt.. PLease help
In your global index.css, make your parent nodes stretch in y-axis, by having these styles:
body: { height: 100vh; }
html,
#root,
.App {
height: 100%;
}
Besides
flex-direction in react-apps is row by default,
so update your Box-styling to :
<Box
sx={{
display: 'flex',
flexDirection: 'column',
bgcolor: 'silver',
height: '100%', // <---here
}}
>
{/** ... */}
</Box>

Mui conditional rendering of one component

I would like to set disableGutters for MUI Container when xs size.
So far I was only able to do it like so:
<Container disableGutters sx={{ display: { xs: 'block', md: 'none' } }}>
...lot of code
</Container>
<Container sx={{ display: { xs: 'none', md: 'block' } }}>
...lot of duplicit code
</Container>
But because there is a lot of duplicit code I don't feel good about this solution, so is there a better way?
What you can do is use the MUI breakpoints like this:
In your component you should add:
import { useMediaQuery, useTheme } from "#mui/material";
inside de component:
const theme = useTheme();
const isExtraSmallSize = useMediaQuery(theme.breakpoints.down("xs"));
and then:
<Container disableGutters={isExtraSmallSize ? true : false} sx={{ display: { xs: 'block', md: 'none' } }}>
...lot of code
</Container>
or what you can do is use isExtraSmallSize to create the conditional rendering you need
A custom hook with theme and useMediaQuery is very useful, I recommend you to do it

How to access values from context in a separate functional component

I'm trying to build a simple light mode/dark mode into my app I saw this example on Material UI for light/dark mode but I'm not sure how I can get access to the value for when the user clicks toggleColorMode in my Header component if it's being set in toggleColorMode function?
I guess my question is how can I get access to the value of light/dark mode of the context in my Header component if it's in a different function?
Here is my code.
import React, { useState, useEffect } from "react";
import MoreVertIcon from "#mui/icons-material/MoreVert";
import DarkModeIcon from "#mui/icons-material/DarkMode";
import LightModeIcon from "#mui/icons-material/LightMode";
import Paper from "#mui/material/Paper";
import { useTheme, ThemeProvider, createTheme } from "#mui/material/styles";
import IconButton from "#mui/material/IconButton";
import Navigation from "../Navigation/Navigation";
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
export const Header = (props) => {
const { mode } = props;
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
console.log("mode is...", mode);
return (
<div className="header-container">
<Paper
elevation={3}
style={{ backgroundColor: "#1F1F1F", padding: "15px" }}
>
<div
className="header-contents"
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div
className="logo"
style={{ display: "flex", alignItems: "center" }}
>
<img
src="/images/header-logo.png"
alt="URL Logo Shortener"
width={"50px"}
/>
<h1 style={{ color: "#ea80fc", paddingLeft: "20px" }}>
URL Shortener
</h1>
</div>
<div className="settings">
<IconButton
sx={{ ml: 1 }}
onClick={colorMode.toggleColorMode}
color="inherit"
aria-label="dark/light mode"
>
{theme.palette.mode === "dark" ? (
<DarkModeIcon
style={{
cursor: "pointer",
marginRight: "10px",
}}
/>
) : (
<LightModeIcon
style={{
cursor: "pointer",
marginRight: "10px",
}}
/>
)}
</IconButton>
<IconButton aria-label="settings">
<MoreVertIcon style={{ color: "#fff", cursor: "pointer" }} />
</IconButton>
</div>
</div>
</Paper>
{/* Navigation */}
<Navigation />
</div>
);
};
export default function ToggleColorMode() {
const [mode, setMode] = React.useState("light");
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
},
}),
[]
);
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode]
);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<Header mode={mode} />
</ThemeProvider>
</ColorModeContext.Provider>
);
}
Read the documentation: createContext, useContext. You need to render a ContextProvider in your parent (or top-level) component, then you can get the data in any component in the tree like const { theme } = useContext(ColorModeContext);.
You don't need to pass the mode as props, put it as one of the values in the context and access it.
Here's how you would render it in your example:
<ColorModeContext.Provider value={{colorMode, theme}}>
<Header />
</ColorModeContext.Provider>
You can pass an object inside the value in the context provider, in other word you can pass the toggle function inside your value to be consumed in the childern. thus you gain an access to change your mode state.
Note that the way changes are determined can cause some issues when passing objects as value, this might trigger unnecessary rerendering see Caveats for more info. or refer to the useContext docs
<ColorModeContext.Provider
value={{ colorMode: colorMode, toggleColorMode: toggleColorMode }}
>
<ThemeProvider theme={theme}>
<Header />
</ThemeProvider>
</ColorModeContext.Provider>

React Admin Layout Component From Scratch

I want to implement a customized Layout for react-admin. I've tried to use their documentation 'https://marmelab.com/react-admin/Theming.html#using-a-custom-layout'
But it didn't work well ( for example we didn't have theme in our component). There is a broken link in the documentation that says you can use it for customizing :(.
I've implemented something right now that works fine right now but I don't know would work completely without problem/side-effects till the end of the project.
import * as React from 'react'
import { MuiThemeProvider, withStyles, createStyles} from '#material-ui/core/styles'
import appTheme from '../config/Theme'
import AppBar from './AppBar'
import Navbar from './Navbar'
const styles = (theme: any) => createStyles({
appFrame: {
display: 'flex',
flexDirection: 'column',
overflowX: 'auto',
},
content: {
display: 'flex',
flexDirection: 'column',
flexGrow: 2,
marginTop: '4em',
padding: theme.spacing.unit * 3,
paddingLeft: 5,
},
contentNoSidebar: {
display: 'flex',
flexGrow: 1,
},
root: {
backgroundColor: theme.palette.background.default,
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
position: 'relative',
zIndex: 1,
},
})
class CustomLayout extends React.Component<any, any> {
public render () {
const {
children,
classes,
logout,
open,
title,
} = this.props
return (
<MuiThemeProvider theme={appTheme}>
<div className={classes.root}>
<div className={classes.appFrame}>
<AppBar title={title} open={open} logout={logout} />
<Navbar/>
<main className={classes.contentNoSidebar}>
<div className={classes.content}>
{children}
</div>
</main>
</div>
</div>
</MuiThemeProvider>
)
}
}
export default withStyles(styles)(CustomLayout)
I appreciate if you could help me in this case.
I see nothing wrong with this code sample. This is indeed the way to go to customize the Layout. Do you have any issue with it ?
Can you open an issue on the react-admin repository about the documentation broken link ?

Resources