Transforming a shared component in react to incorporate material theme

In my setup, I have two React projects - Parent and Common project. The Common project contains common components like header and footer that are shared between multiple projects.

In the Parent project, I have a material theme defined and configured using MuiThemeProvider in the standard way. However, I noticed that this theme object is only available inside components defined in the Parent project and not in the shared Common project.

I would appreciate any suggestions on how to make this theme object accessible in the shared Common project as well.

Additional details added on Oct 30, 2020

Parent Component

import React from "react";
import "./App.css";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import themeDefault from "./CustomTheme.js";
import { MuiThemeProvider } from "@material-ui/core/styles";
import { createMuiTheme } from "@material-ui/core/styles";
import Dashboard from "./containers/Dashboard/Dashboard";
import { Footer, Header } from "my-common-react-project";

function App() {
  const routes = () => {
    return (
      <BrowserRouter>
        <Switch>
          <Route exact path="/" component={Dashboard} />
        </Switch>
      </BrowserRouter>
    );
  };
  return (
    <MuiThemeProvider theme={createMuiTheme(themeDefault)}>
      <div className="App">
        <Header
          logo="some-logo"
          userEmail={"test@email"}
        />
        ... app components here..
        <Footer />
      </div>
    </MuiThemeProvider>
  );
}

export default App;

Shared component

import React from "react";
import {
  Box,
  AppBar,
  Toolbar,
  Typography,
} from "@material-ui/core/";

import styles from "./Header.styles";
import PropTypes from "prop-types";

const Header = (props) => {
  const classes = styles();
  const { options, history } = props;
  const [anchorEl, setAnchorEl] = React.useState(null);
  const handleCloseMenu = () => {
    setAnchorEl(null);
  };

  const goto = (url) => {
    history.push(url);
  };
  return (
    <Box component="nav" className={classes.headerBox}>
      <AppBar position="static" className={classes.headerPart}>
        <Toolbar className={classes.toolBar}>
          {localStorage && localStorage.getItem("isLoggedIn") && (
            <>
              {options &&
                options.map((option) => (
                  <Typography
                    key={option.url}
                    variant="subtitle1"
                    className={classes.headerLinks}
                    onClick={() => goto(option.url)}
                  >
                    {option.name}
                  </Typography>
                ))}
            </>
          )}
        </Toolbar>
      </AppBar>
    </Box>
  );
};

Header.propTypes = {
  options: PropTypes.array
};
export default Header;

Shared Component style

import { makeStyles } from "@material-ui/core/styles";

export default makeStyles((theme) => ({
  headerPart: {
    background: "white",
    boxShadow: "0px 4px 15px #00000029",
    opacity: 1,
    background: `8px solid ${theme.palette.primary.main}`
    borderTop: `8px solid ${theme.palette.primary.main}`
  }
}));

The issue I'm facing is that even though the Parent component has defined theme.palette.primary.main as Red color, the Header component is picking up a different default theme with theme.palette.primary.main set to blue.

This results in the header being displayed in blue color while the body remains in red. Any suggestions on how I can configure the theme object so that the Header also picks up the theme.palette.primary.main from the parent theme object?

Answer №1

This is the solution provided for mui V5

import { useTheme } from '@mui/material/styles' // /!\ There was a typo in the official documentation that has been corrected

function DeepChild() {
  const theme = useTheme();
  return <span>{`spacing ${theme.spacing}`}</span>;
}

Extracted from mui documentation

Answer №2

To pass the theme object to nested components within a ThemeProvider, you have two options: useTheme or withTheme.

  • For functional components, use the useTheme hook.
  • For class-based components that cannot use hooks, use the withTheme Higher Order Component.
function NestedComponent() {
  const theme = useTheme<MyTheme>();

  return <span>{`spacing ${theme.spacing}`}</span>;
}

class NestedClass extends React.Component {
  render() {
    const { theme } = this.props;
    return <span>{`spacing ${theme.spacing}`}</span>;
  }
}

const ThemedNestedClass = withTheme(NestedClass);

Check out the Live Demo:

Demo Link

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

Learn how to remove the border and incorporate a background color into the outlined variant of MUI TextField

Looking to customize the outlined variant of a TextField in Material UI? Below, I aim to remove the border or change it to white color, and also give it a different background color. I've been using styled components in my app, and though I've tr ...

How can we include additional types for external npm packages in a React TypeScript project?

Recently, I encountered an issue while using the react-microsoft-login package from npm. I included a button in the children property and received a typescript error stating that "property 'children' does not exist on type 'intrinsicattribut ...

Is the useEffect hook executed twice in a production environment?

I'm facing a straightforward question here. I know that during development, running a code twice can help identify bugs faster. However, now I'm wondering if there's something I should configure to prevent this from happening in production w ...

Dynamic row height in Material-UI DataGrid adjusting based on text content

When working with the DataGrid, I'm struggling to find a way to adjust row heights based on the length of text in each cell dynamically. I thought about utilizing renderCell on the column containing longer text and incorporating the <Typography> ...

Tips for positioning an MUI element inside a container to extend to the edge of the browser window

Currently, I'm working on a project with a Material-UI (MUI) container that contains a Stack element. Within this Stack, there are two Box elements displayed in a row, each set to take up 50% of the width. In my design, I want the second box to break ...

The error message 'Cannot read property 'navigate' of undefined' is displayed because the function '_this.props.navigation.navigate' is not

I'm facing an issue trying to access 'Home' from Form.js. Despite my efforts in arrowF, routes, and other methods, the same error persists. How can I resolve this? In my Form.js file, when I call onPress=(), I have tried using functions, ...

Having trouble deleting the value and deselecting the checkbox item?

Feeling a bit confused about a coding issue I'm facing. The problem lies in the categories listed in my database, which I fetched and used to create a post. Now, I'm attempting to edit that post. The categories are in checkbox format, where check ...

Issue arises when the backend is running causing errors in the ReactJS frontend

I am encountering an issue with my React Js frontend and node express backend setup. When I run the frontend using npm start, everything works fine. However, when I also start the backend, I get this error: TypeError: Cannot read property 'map' o ...

Modify Material UI - Container for Dialog

Is it feasible to pass or modify a container for material ui components such as Dialog, Popper, and others? (https://material-ui.com/api/dialog/) These components typically render their popups on the document.body. The main goal here is to display the dia ...

Can you specify a default value in react-select using ReactJS?

After extensive research on the issue, I have been unable to find a solution. I am trying to display a specific value by default in the select box in the view. This is my select code: <Select options={getMainCategory.data.map((item) => { ...

Creating a stylish Material UI design step by step

When working with Vue using Vuetify, I rely on <v-content> to create my layouts. However, when exploring Material UI, I couldn't find a similar component. Is there a way to translate this Vuetify layout into Material UI? <v-app> <v- ...

The name property of event.currentTarget is now being returned as currentTarget

I am facing an issue with my handleChange function in typescript. When I try to retrieve the name attribute from a text field and log it, it returns 'currentTarget' instead of the assigned name. Additionally, the value is showing up as undefined. ...

Looking to open a new tab in React when a button is clicked? I also need to pass some data to the new page

I'm currently developing a feature where users can raise an invoice by clicking on a button. When the button is clicked, an API call will be made and upon receiving the response, I need to send some data to a specific page (RaisedInvoice.jsx) that sho ...

The Recoil Nexus encountered an error: the element type provided is not valid. It should be a string for built-in components or a class/function for composite components, but an object was

Encountered the following error message: Error - Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. at ReactDOMServerRenderer.render ... This issue arose when integra ...

Tips for building a versatile fetch function that can be reused for various JSON formats within a React application

Using the fetch method in various components: fetch(url) .then(result => { if (!result.ok) { throw new Error("HTTP error " + result.status) } return result.json() }) .then(result => { ...

Leveraging material elements in React applications

I have been studying the guide on Material UI Beta for react and I am interested in creating a simple component using the Drawer element. Here is an example code from the official documentation that demonstrates how to build such a Component. import React ...

Developing an international loading animation with the power of React and Redux

I am looking to create a reusable spinner but unsure of the best approach. After trying out two methods, I feel like I need some guidance as I am still new to React. Method 1: MyComponent.js const MyComponent = (props) => { ... return ( ...

Changing the color of a textarea in ReactJS using materialUI when focused

I have been experimenting with changing the default color of a TextField in material UI using CSS. After referencing the CSS injection order in material UI and some stackoverflow answers, I was able to come up with a solution. However, I also tried a diffe ...

Having trouble with mongoose-paginate and react using material-ui's TablePagination component? Encountering issues where the second page onwards does not render after

I am still learning my way around React, and I believe there is a crucial component missing in this particular React setup. Any assistance leading to a solution will be greatly appreciated. The Functionality I'm Striving For Here - I aim to incorpora ...

Why isn't the function in my React child component passing its parameters to the parent component's function as expected?

In the parent: const [currentPinPosition, setCurrentPinPosition] = React.useState({ lat: 0 , lng: 0 }); const updateCurrentPinPos = (position) => { console.log(position); setCurrentPinPosition({ lat: position.lat, lng: position.lng }); }; / ...