The styled component is not reflecting the specified theme

I have a suspicion that the CSS transition from my Theme is not being applied to a styled component wrapped in another function, but I can't pinpoint the exact reason. I obtained the Basic MUI Dashboard theme from this source and here. Initially, integrating it into my project worked smoothly. However, to streamline the implementation of the original 'Dashboard.tsx' file, I refactored the 'Drawer' and 'AppBar' styled components into separate files. Below is the code for the 'Drawer' implementation in the initial demo; besides wrapping this code within a 'Sidebar' function, everything else remains consistent with a similar version for the 'AppBar'.

function Sidebar(open: boolean, drawerWidth: number, toggleDrawer: any){

    const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
        ({ theme, open }) => ({
            
            '& .MuiDrawer-paper': {
                position: 'relative',
                whiteSpace: 'nowrap',
                width: drawerWidth,
                transition: theme.transitions.create('width', {
                    easing: theme.transitions.easing.sharp,
                    duration: theme.transitions.duration.enteringScreen,
                }),
                boxSizing: 'border-box',
                ...(!open && {
                    overflowX: 'hidden',
                    transition: theme.transitions.create('width', {
                        easing: theme.transitions.easing.sharp,
                        duration: theme.transitions.duration.leavingScreen,
                    }),
                    width: theme.spacing(7),
                    [theme.breakpoints.up('sm')]: {
                        width: theme.spacing(9),
                    },
                }),
            },
        }),
    );

    return (
        <Drawer variant="permanent" open={open}>
            <Toolbar
                sx={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'flex-end',
                    px: [1],
                }}
            >
                <IconButton onClick={toggleDrawer}>
                    <ChevronLeftIcon />
                </IconButton>
            </Toolbar>
            <Divider />
            <List component="nav">
                {NavItems }
                <Divider sx={{ my: 1 }} />
            </List>
        </Drawer>
    );
}

export default Sidebar;

Further, in the 'Dashboard.tsx' file, the following code is present:

<ThemeProvider theme={mdTheme}>
    //other components omitted
    {Sidebar(open, drawerWidth, toggleDrawer)}; 
    //other components omitted
</ThemeProvider>

The three props passed to 'Sidebar' are derived from the original demo (where 'open' signifies a state value, 'drawerWidth' defines the sidebar's width, and 'toggleDrawer' operates as a function to update the state). Despite implementing these changes and running the application, users can still toggle the drawer open and shut like in the original demo; however, the smooth transition evident initially seems to be absent, resulting in a rather abrupt opening and closing of the drawer.

I experimented with various implementations involving 'withTheme', 'useTheme', etc., but none appeared to yield the desired outcome. A related query implied that including 'position:relative' within the Drawer container was necessary, yet this parameter seems to be already incorporated during the 'styled' call (to the best of my understanding). Any assistance on this matter would be greatly appreciated.

Answer №1

When you define your Drawer component type within the Sidebar function, a new component type is created every time it renders. As a result, the Drawer is unmounted from the DOM and then remounted as a completely new element in the DOM with each re-render, causing any transitions to fail.

It seems like the only reason for defining it inside of the Sidebar function is to access drawerWidth. To resolve this issue, you can move your styled Drawer to the top level and pass drawerWidth as a prop, as demonstrated in the example below:

import { styled } from "@mui/material/styles";
import MuiDrawer, { DrawerProps } from "@mui/material/Drawer";

interface CustomDrawerProps extends DrawerProps {
  drawerWidth: number;
}
const Drawer = styled(MuiDrawer, {
  shouldForwardProp: (prop) => prop !== "drawerWidth"
})<CustomDrawerProps>(({ theme, open, drawerWidth }) => ({
  "& .MuiDrawer-paper": {
    position: "relative",
    whiteSpace: "nowrap",
    width: drawerWidth,
    transition: theme.transitions.create("width", {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen
    }),
    boxSizing: "border-box",
    ...(!open && {
      overflowX: "hidden",
      transition: theme.transitions.create("width", {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen
      }),
      width: theme.spacing(7),
      [theme.breakpoints.up("sm")]: {
        width: theme.spacing(9)
      }
    })
  }
}));
function Sidebar(open: boolean, drawerWidth: number, toggleDrawer: any) {
  return (
    <Drawer variant="permanent" open={open} drawerWidth={drawerWidth}>
...

https://codesandbox.io/s/styled-drawer-0r3jik?fontsize=14&hidenavigation=1&theme=dark

Other answers addressing similar issues:

  • React Beginner Question: Textfield Losing Focus On Update
  • React Material-UI menu anchor broken by react-window list

More information on organizing components: https://react.dev/learn/your-first-component#nesting-and-organizing-components

Excerpt:

Components can render other components, but you must never nest their definitions. Instead, define every component at the top level.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: Attempting to access an undefined property ('call') on Next.js is causing a TypeError

Exploring the realms of Next.js and Typescript for a new project! My goal is to utilize next.js with typescript and tailwind CSS by simply entering this command: npx create-next-app -e with-tailwindcss my-project Smooth sailing until I hit a snag trying t ...

Is there a way to bypass the initial result when using document.querySelectorAll?

this is my own unique html content <div class="content-body"> <table style="text-align:center;" class="table table-bordered"> <tbody> <tr> <th>Text Line</th> </tr> <tr> <td> ...

Is it feasible to evaluate a Typescript method parameter decorator at request time in a nodejs+nestjs environment rather than just at build time?

Looking to simplify my handling of mongodb calls with and without transactions in a single service method by writing a decorator. This would help eliminate the repetition of code and make things more efficient. Key points for usage: • Service class has ...

Issues with rendering in-line styles in ReactJS after a state update

I'm currently working on implementing a basic state change for a button in React. 'use strict'; class ReactButton extends React.Component { constructor(props) { super(props); this.state = {hovering: false}; } onClick() { ...

What is the process for updating tabs and their content in React?

Here is where the error occurs in my JavaScript code. I have successfully implemented it in HTML, CSS, and simple JavaScript, but encountered issues when trying to do so in React. My goal is to switch tabs and their corresponding data/content: ...

What is the best way to use Google Material-Design-Icons in my project once I have installed it

Once I've installed the material-design-icons package using npm, how can I incorporate them into my React application? The instructions provided here do not mention the npm method. ...

Find a specific element within a React application

I created a Logout button component in my React application that I want to position at the top right corner of the screen. render() { <LogoutButtonComponent height: , backgroundColor: /> } Unfortunately, I am unable to set any values for height ...

Challenges encountered with JSX format in React's TicTacToe guide

While trying out React's tutorial on building a TicTacToe game (https://react.dev/learn/tutorial-tic-tac-toe) in my local development environment, I encountered this error message after copying and pasting the code snippet below from the tutorial. exp ...

Dynamically update tab content in material UI

Within my React application page, I have a div with Material UI tabs. There are two tabs, one of which contains a list view also created with Material UI. I am looking to implement a behavior where clicking on a list item within the list view will result i ...

Updating state with new data in React: A step-by-step guide

Recently, I delved into the world of reactjs and embarked on a journey to fetch data from an API: constructor(){ super(); this.state = {data: false} this.nextProps ={}; axios.get('https://jsonplaceholder.typicode.com/posts') ...

Having difficulty in utilizing localStorage to update the state

I've attempted to log back in using the stored credentials, however it's not working despite trying everything. The dispatch function is functioning properly with the form, but not when accessing localStorage. App.tsx : useEffect(() => { ...

Get rid of the arrow that is displayed when using the `time` input type in HTML5

Recently, I encountered an issue with the default HTML5 code snippet. My custom background looked perfect except for a pesky black arrow appearing on the right side. In this image, you can see the problematic black arrow that needs to be removed. I attemp ...

Positioning MDL cards in HTML documents

Seeking guidance on positioning MDL cards alongside existing text. I've attempted various methods without success so far, and the desired outcome has not been achieved. The goal is to have text aligned to the left (which is currently satisfactory) wi ...

Ensure Focus Retention Upon Clicking Inside Iframe with li a:focus

How can I prevent my ul.SideNav_Main li a:focus class from losing focus when I click on the iframe or elsewhere on the page? Shouldn't it maintain focus until I click on another URL in the list? Is it possible to solve this issue with just CSS, or wo ...

evt.target consistently returns the initial input within the list of inputs

My React file uploader allows users to attach multiple file attachments. Each time a user clicks on an input, I retrieve the data-index to identify the input position. renderFileUploader() { let file_attachment = this.state.file_attachment.map(fun ...

Samsung devices exclusively showcase background in responsive design

I am encountering a major problem with my website design, specifically with its compatibility on mobile devices. To ensure its responsiveness, I have tested the design on my iPhone, iPad, and Windows Phone. Unfortunately, since I lack an Android device, I ...

Revise Swagger UI within toggle button switch

My project aims to showcase three distinct OpenApi definitions within a web application, enabling users to explore different API documentation. The concept involves implementing a toggle button group with three buttons at the top and the Swagger UI display ...

Passing references between multiple components

I'm currently working on an application using Material-UI in conjunction with styled-components. I am faced with the challenge of passing a ref down to the root <button> node that is created by Material-UI. Material-UI provides a buttonRef prop ...

Element that moves in conjunction with scroll (without using position:fixed)

A while back, I stumbled upon something that I can't seem to find now. I'm looking for a shopping cart similar to the one on the Apple store - a div element that isn't positioned absolutely or fixed. Ideally, it would be located in the cente ...

When it comes to using brackets and HTML, I keep receiving an error message indicating that there is no index file

I'm having trouble with this code - it works fine in Code Academy, but I am new to HTML and trying to practice outside of the platform. Every time I try to live preview in Brackets, I get an error message saying "make sure there is an html file or tha ...