Utilizing Material UI and TypeScript to effectively pass custom properties to styled components

Currently, I am utilizing TypeScript(v4.2.3) along with Material UI(v4.11.3), and my objective is to pass custom props to the styled component.

import React from 'react';
import {
  IconButton,
  styled,
} from '@material-ui/core';

const NavListButton = styled(IconButton)(
 ({ theme, panelOpen }: { theme: Theme; panelOpen: boolean }) => ({
   display: 'inline-block',
   width: 48,
   height: 48,
   borderRadius: 24,
   margin: theme.spacing(1),
   backgroundColor: panelOpen ? theme.palette.secondary.dark : 'transparent',
 }),
);

...

const Component: React.FC<Props> = () => {
  return (
    <NavListButton panelOpen={true} />
  );
};

The functionality works smoothly, but upon checking the browser console, it shows an error message.

Warning: React does not recognize the `panelOpen` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `panelopen` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
    at button
    at ButtonBase ...

Is there a way to resolve this issue without resorting to using the styled-components module and sticking to using styled from Material UI?

Additionally, another related query arises.

I have a requirement to incorporate media queries into styled components, however, when attempted, it throws a

TypeError: Cannot read property 'addRule' of null
.

const PrintableTableContainer = styled(TableContainer)(() => ({
  '@media print': {
    '@page': { size: 'landscape' },
  },
}));

https://i.stack.imgur.com/XtzcF.png

I also experimented with the following approach.

const PrintableTableContainer = styled(TableContainer)`
  @media print {
    @page { size: landscape }
  }
`;

However, this alternative prompted the following error:

Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'CreateCSSProperties<(value: string, index: number, array: readonly string[]) => unknown> | ((props: { theme: Theme; } & ((value: string, index: number, array: readonly string[]) => unknown)) => CreateCSSProperties<...>)'.
  Type 'TemplateStringsArray' is not assignable to type 'CreateCSSProperties<(value: string, index: number, array: readonly string[]) => unknown>'.
    Types of property 'filter' are incompatible.
...

Answer №1

Just sharing my thoughts, I hope the solution I suggest proves to be helpful for your situation.

The root of the issue lies in the version conflict within material-ui, where your project seems to be utilizing both version 4 and version 5 simultaneously.

Step 1: Upgrade to material-ui v5

  • @next version = v5
  • Install material-ui along with styled-engine to incorporate styled-components
// npm
npm install @material-ui/core@next @material-ui/styled-engine-sc@next styled-components
npm install --save-dev @types/styled-components


// yarn 
yarn add @material-ui/core@next @material-ui/styled-engine-sc@next styled-components
yarn add --dev @types/styled-components

Step 2: Implement react-app-rewired

As the default material-ui styled-engine is set to emotion, we need to override the webpack configuration to use styled-components instead.

The Official Documentation provides guidance on using styled-components in material-ui:

For create-react-app, install react-app-rewired

// npm 
npm install --save-dev react-app-rewired customize-cra

// yarn
yarn add --dev react-app-rewired customize-cra

Step 3: Customize webpack Configuration

Refer to the official example: https://github.com/mui-org/material-ui/tree/next/examples/create-react-app-with-styled-components-typescript

  • Create a new file named config-overrides.js
  • Update styled-engine path to point to styled-engine-sc path
// config-overrides.js
const { addWebpackAlias, override } = require('customize-cra');

module.exports = override(
  addWebpackAlias({
    '@material-ui/styled-engine': '@material-ui/styled-engine-sc',
  }),
);

Step 4: Utilize material-ui with styled-components

import { IconButton, styled, TableContainer, Theme } from "@material-ui/core";

const NavListButton = styled(IconButton)(
  ({ theme, $panelOpen }: { theme?: Theme, $panelOpen: boolean }) => ({
    display: "inline-block",
    width: 48,
    height: 48,
    borderRadius: 24,
    margin: theme?.spacing(1),
    backgroundColor: $panelOpen ? theme?.palette.secondary.dark : "transparent"
  })
);

const PrintableTableContainer = styled(TableContainer)(() => ({
  "@media print": {
    "@page": { size: "landscape" }
  }
}));

...

<NavListButton $panelOpen={true} />
<PrintableTableContainer />

In regards to the first question,

React does not recognize the `panelOpen` prop on a DOM element. 
.

styled-components offer transient props - $ as a solution to prevent custom props from being passed directly to the DOM.

https://styled-components.com/docs/api#transient-props


A demonstration repository is available for reference and troubleshooting if you encounter any difficulties implementing the changes

Answer №2

Encountered a comparable issue. I faced the following situation:

import styles from './MabSidebar.styles';
...
const Sidebar = styled(Box)(styles);

Resolved it hastily by resorting to a quick fix:

const Sidebar = styled(Box)(styles as any);

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

It appears there was a mistake with [object Object]

Hey there, I'm currently working with Angular 2 and trying to log a simple JSON object in the console. However, I keep encountering this issue https://i.stack.imgur.com/A5NWi.png UPDATE... Below is my error log for reference https://i.stack.imgur.c ...

Navigating the onSubmit with Formik in React: Tips and Tricks

I have a query regarding my usage of Formik in my React application. Within the onSubmit function, I am making an API call to a service. If this call fails, I want to immediately stop the rest of the submission process without executing any further action ...

The use of Next.js v12 middleware is incompatible with both node-fetch and axios

I am facing an issue while developing a middleware that fetches user data from an external endpoint using Axios. Surprisingly, Axios is not functioning properly within the middleware. Below is the error message I encountered when using node-fetch: Module b ...

What is the best way to delay a recursive JavaScript function for 3 seconds?

Before writing this post, I have already come across the following questions: how-to-pause-a-settimeout-call how-to-pause-a-settimeout-function how-to-pause-a-function-in-javascript delay-running-a-function-for-3-seconds Question The below code snipp ...

Grunt Typescript is encountering difficulty locating the angular core module

Question Why is my Grunt Typescript compiler unable to locate the angular core? I suspect it's due to the paths, causing the compiler to not find the libraries in the node_modules directory. Error typescript/add.component.ts(1,25): error TS23 ...

Uncertain about the distinction between reducers and dispatchers when it comes to handling actions

I'm feeling a bit confused regarding reducers and dispatchers. While both receive actions as parameters, it doesn't necessarily mean that the actions I use in my dispatchers are the same as those used in my reducers, correct? For example, if I h ...

The debounced function in a React component not triggering as expected

I am facing an issue with the following React component. Even though the raiseCriteriaChange method is being called, it seems that the line this.props.onCriteriaChange(this.state.criteria) is never reached. Do you have any insights into why this.props.onC ...

Error encountered: Next.js with Material-UI - The `className` prop does not match on the server

I've been developing a NextJS application that utilizes React Material-Ui, and I keep encountering the Prop 'className' did not match. error. I have already made the necessary adjustments to my _app.tsx and _document.tsx based on the officia ...

Tips for concealing validation errors in React Js when modifying the input field

I have recently started working with ReactJs, and I've implemented form validation using react-hook-form. After submitting the form, the errors are displayed correctly. However, the issue arises when I try to update the input fields as the error messa ...

Is there a way for me to provide the product ID based on the selected product?

Is there a way to store the IDs of selected products in a dynamic form with multiple product options? I am able to see the saved products in the console.log(fields, "fields");, but how can I also save the selected product IDs? Any guidance on th ...

Utilizing the [mat-dialog-close] directive within an Angular dialog component

While attempting to utilize the suggested code in the dialog template for opening a dialog component to either confirm or cancel an action, I encountered an error with the following message. Why did this happen? Property mat-dialog-close is not provided by ...

Compilation of Angular 6 project is failing due to error TS1005: Expected ',' instead of the symbol used

I keep encountering an error message whenever I try to compile my code. ERROR in src/app/form/form.component.ts(22,39): error TS1005: ',' expected. Below is the snippet of code where the error is pointing: import { Component, OnInit } from &ap ...

Navigating the maze of Material UI in React with TypeScript

I have a functioning code, but I am trying to incorporate Material UI into it. However, when I replace 'input' with 'TextField', I encounter the following error: Uncaught (in promise) Error: Request failed with status code 422 at cr ...

Testing server sent events with Angular solely using Karma-Jasmine

I am currently developing a web application using Angular for the frontend and Python for the backend. My implementation involves utilizing server-sent events (SSE) to stream data from the server to the user interface. While everything is functioning prope ...

The issue of the color CSS rule not being applied to the button element when transitioning from disabled to enabled on browsers like Safari 14+ is a common challenge

There seems to be an issue with frontend form validation code affecting the disabled attribute of a submit button within a form. Two different css rules are applied for the enabled and disabled states, including changes in the text color of the button ele ...

The importance of handling undefined values in TypeScript and React

There is a condition under which the IconButton element is displayed: {value.content && <IconButton aria-label="copy" onClick={() => copyContent(value.content)}> <ContentCopy /> </IconButton> } However, a ...

Using the -t or --testNamePattern in Jest will execute all tests

Currently, I have set up my testing framework using jest and ts-jest based on the guidelines provided by the ts-jest documentation. When I execute the command yarn test --listTests, I can identify the specific test file I intend to run: processNewUser.ts ...

Switch the ngClass on the appropriate ancestor element for the dropdown menu

Utilizing Angular CLI version 8.3.0, I aim to construct a sidebar featuring a drop-down menu. My objective is to apply the "open" class to toggle the opening of the drop-down section. However, the current challenge I am encountering is that when I click to ...

Save the data in Redux and access it back

I am currently using material-ui-dropzone to upload an array of files and store them in redux However, when I try to retrieve the file from the redux state, it is not recognized as type "File" and appears differently in devtools https://i.stack.imgur.com ...

Enhancing the design of an HTML tag element with a custom style using ReactJS material-ui

I am currently working on a ReactJS file that incorporates an Icon from the Material-UI library. import LocalHospital from "@material-ui/icons/LocalHospital"; Later in the code, I am utilizing this icon within another HTML tag like so: <div c ...