React & Material-UI:使用 TypeScript 在 createStyles() 中未定义主题

IT技术 reactjs typescript material-ui
2021-05-26 17:51:46

我正在使用 TypeScript 学习 React,并在前端使用 Material UI 框架。我尝试使媒体查询正常工作,但出现错误:

未捕获的类型错误:无法读取样式中未定义的属性 'up' (webpack-internal:///./app/components/navigation/Toolbar/index.tsx:59)

这是对应的代码:

const styles = ({breakpoints}: Theme) => createStyles( {
    grow: {
        flexGrow: 1
    },
    menuButton: {
        marginLeft: -12,
        marginRight: 20
    },
    sectionDesktop: {
        display: 'none',
        [breakpoints.up('md')]: {
            display: 'flex'
        }
    },
    sectionMobile: {
        display: 'flex'
    },
})

样式通过以下方式传递给组件:

export default withStyles(styles)(Toolbar)

我读到不需要创建自定义主题,因为默认主题将自动传递给函数。但是,主题的断点属性未定义,导致页面空白。

谢谢你的帮助

编辑

这是组件的代码,它在没有任何其他组件的情况下仍然会产生问题。

import * as React from 'react'
import {
    Theme
} from '@material-ui/core'
import {
    createStyles,
    WithStyles,
    withStyles
} from '@material-ui/styles'
// import Drawer from '../Drawer'

const styles = ({breakpoints}: Theme) => createStyles( {
    grow: {
        flexGrow: 1
    },
    menuButton: {
        marginLeft: -12,
        marginRight: 20
    },
    sectionDesktop: {
        display: 'none',
        [breakpoints.up('md')]: {
            display: 'flex'
        }
    },
    sectionMobile: {
        display: 'flex'
    },
})

namespace Toolbar {
    interface Props {
    }

    export interface State {
        isOpen : boolean
        mobileMoreAnchorEl? : EventTarget & HTMLElement
    }

    export type AllProps = Props & WithStyles<typeof styles>
}

class Toolbar extends React.Component<Toolbar.AllProps, Toolbar.State> {
    constructor(props: Toolbar.AllProps, context?: any) {
        super(props, context);
        this.state = { isOpen: false, mobileMoreAnchorEl: undefined}
    }

    render() {
        const { classes } = this.props
        // const { isOpen } = this.state

        return(
            <React.Fragment>
                <div className={classes.sectionDesktop}>
                    Hello
                </div>
                <div className={classes.sectionMobile}>
                    World
                </div>
            </React.Fragment>
        )
    }

}

export default withStyles(styles)(Toolbar)

main.tsx(又名 index.js)看起来像这样:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import { configureStore } from 'app/store';
import { Router } from 'react-router';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import { App } from './app';

// prepare store
const history = createBrowserHistory()
const store = configureStore()
const theme = createMuiTheme()

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <MuiThemeProvider theme={theme} >
        <App />
      </MuiThemeProvider>
    </Router>
  </Provider>,
  document.getElementById('root')
);

因此,添加 MuiThemeProvider 无济于事。

1个回答

更新

在第一次写这个答案的时候,@material-ui/styles是不稳定的。它不再是(从 v4 开始),但通常仍然最好从 from 导入,@material-ui/core/styles因为从 @material-ui/styles.


你可以阅读在这里@material-ui/styles不稳定(alpha版本)。

您会在我的 CodeSandbox 中注意到我正在使用:

import { withStyles, createStyles } from "@material-ui/core/styles";

而不是从@material-ui/styles. 当我使用与您相同的导入时,我能够重现您的问题。

编辑 82kp602xqj


v5 更新

在V5,使用情况makeStyleswithStyles已淘汰,他们从被拆除@material-ui/core,并只能通过访问@material-ui/styles在V5,makeStyleswithStyles没有进入主题,除非您提供通过访问ThemeProvider(并为实现这一目标,你应该同时使用的最新版本V5工作@material-ui/core@material-ui/styles)。下面是一个有效的 v5 示例。

import React from "react";
import ReactDOM from "react-dom";
import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import { withStyles } from "@material-ui/styles";
const styles = ({ breakpoints }) => ({
  grow: {
    flexGrow: 1
  },
  menuButton: {
    marginLeft: -12,
    marginRight: 20
  },
  sectionDesktop: {
    display: "none",
    [breakpoints.up("md")]: {
      display: "flex"
    }
  },
  sectionMobile: {
    display: "flex"
  }
});
const MyToolbar = (props) => {
  return (
    <>
      <div className={props.classes.sectionDesktop}>Section Desktop</div>
      {props.children}
      <div className={props.classes.sectionMobile}>Section Mobile</div>
    </>
  );
};
const theme = createTheme();
const StyledToolbar = withStyles(styles)(MyToolbar);
function App() {
  return (
    <ThemeProvider theme={theme}>
      <StyledToolbar>
        <div>Hello</div>
        <div>CodeSandbox</div>
      </StyledToolbar>
    </ThemeProvider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

使用样式编辑 v5