Как получить доступ к теме материала в общем компоненте в react?

#reactjs #material-ui #react-material

#reactjs #материал-пользовательский интерфейс #react-материал

Вопрос:

У меня есть два родительских проекта react и общий проект (содержит общий компонент, такой как верхний и нижний колонтитулы)

У меня есть тема материала, определенная в родительском и настроенная стандартным способом MuiThemeProvider .

Однако этот объект темы доступен внутри компонентов, определенных в Parent, но не в share project common.

Предложения приветствуются.

Добавлено ниже более подробная информация 30 октября 2020 г.

Родительский компонент

 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;
  

Общий компонент

 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 amp;amp; localStorage.getItem("isLoggedIn") amp;amp; (
            <>
              {options amp;amp;
                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;
  

Стиль общего компонента

 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}`
  }
}));
  

Родительский компонент определен theme.palette.primary.main , скажем, как красный цвет, и я ожидаю, что он будет применен в заголовке, но он выбирает другой объект темы (по умолчанию), который имеет theme.palette.primary.main синий цвет.

В результате мой заголовок будет синего цвета, а тело — цвета чтения.

Любое предложение, как настроить этот объект темы, чтобы заголовок тоже выбирал theme.palette.primary.main из родительского объекта темы.

Комментарии:

1. material-ui.com/styles/advanced/…

Ответ №1:

вот ответ для mui V5

 import { useTheme } from '@mui/material/styles' // /! I fixed a typo from official doc here

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

Взято из документации mui

Ответ №2:

Вы можете использовать либо useTheme или withTheme для внедрения объекта темы в любые вложенные компоненты внутри ThemeProvider .

  • Используйте useTheme хук в функциональных компонентах
  • Используйте withTheme HOC в компонентах на основе классов (которые не могут использовать hook)
 function DeepChild() {
  const theme = useTheme<MyTheme>();

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

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

const ThemedDeepChildClass = withTheme(DeepChildClass);
  

Живая демонстрация

Редактировать демонстрационный материал (разветвленный)

Комментарии:

1. мои компоненты находятся в другом проекте react, а заголовок общего компонента использует тему по умолчанию, а не тему, которую я установил в поставщике темы. таким образом, этот подход не устранил проблему

2. @Ashutosh вы упускаете из виду, что общие компоненты нравятся Header или Footer могут быть в любых проектах, которые они хотят, пока они находятся внутри ThemeProvider на верхнем уровне приложения, они могут иметь доступ к данным темы из контекста темы, если вы хотите использовать тему по умолчанию, просто вызовитебез createMuiTheme() параметров и передайте его ThemeProvider наверх.

3. @Ashutosh Вы заключили свой общий проект в any ThemeProvider ?

4. @NearHuscarl и Loi. Я просто добавил пример кода и детали для большей ясности. Заранее спасибо за помощь