如何在makeStyles中使用“主题”和“道具”?

时间:2019-05-13 11:22:18

标签: material-ui

如何编写makeStyles(),以便它可以同时使用主题变量和道具?

我已经尝试过了:

const useStyles = makeStyles(theme => ({
  appbar: props => ({
    boxShadow: "none",
    background: "transparent",
    marginTop: theme.spacing(2),
    marginBottom: theme.spacing(2),
    color: theme.palette.getContrastText(props)
  }),
}));

并在组件中使用以下命令对其进行调用:

const classes = useStyles(backgroundColor);

backgroundColor是类型为CSSProperties["backgroundColor"]的组件上的道具

但是我得到了错误:

TypeError: Cannot read property 'rules' of undefined
    at RuleList.onUpdate (C:\Users\...\node_modules\jss\dist\jss.cjs.js:944:14)
    at RuleList.update (C:\Users\...\node_modules\jss\dist\jss.cjs.js:923:12)
    at StyleSheet.update (C:\Users\...\node_modules\jss\dist\jss.cjs.js:1178:39)
    at attach (C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:141:18)
    at C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:262:7
    at useSynchronousEffect (C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:207:14)
    at C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:254:5
    at Layout (C:\Users\...\.next\server\static\development\pages\index.js:1698:17)
    at processChild (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:2888:14)
    at resolve (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:2812:5)
    at ReactDOMServerRenderer.render (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:3202:22)
    at ReactDOMServerRenderer.read (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:3161:29)
    at renderToString (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:3646:27)
    at render (C:\Users\...\node_modules\next-server\dist\server\render.js:86:16)
    at renderPage (C:\Users\...\node_modules\next-server\dist\server\render.js:211:20)
    at ctx.renderPage (C:\Users\...\.next\server\static\development\pages\_document.js:2404:22)

  100 |   handleSignUpClick,
  101 |   backgroundColor
  102 | }) => {
> 103 |   const classes = useStyles(backgroundColor);
  104 |   return (
  105 |     <AppBar className={classes.appbar}>
  106 |       <Container maxWidth="lg">

编辑:我正在使用4.0.0-beta.1版本的材质核心和样式

4 个答案:

答案 0 :(得分:1)

您需要将对象而不是字符串传递给useStyles

所以代替:

const classes = useStyles(backgroundColor);

您应该拥有:

const classes = useStyles(props);

const classes = useStyles({backgroundColor});

然后您可以使用以下方法获得backgroundColor:

color: theme.palette.getContrastText(props.backgroundColor)

这是一个可行的示例: https://codesandbox.io/s/o7xryjnmly

答案 1 :(得分:0)

经过测试:

def create_mesh(a):
    m,n = a.shape
    out = np.empty((m,m,2*n),dtype=a.dtype)
    out[...,:n] = a[:,None]
    out[...,n:] = a
    return out.reshape(-1,2*n)

JavaScript示例:

my-component.js

"@material-ui/core": "^4.0.0-beta.1",
"@material-ui/styles": "^4.0.0-rc.0",

my-component.styles.js

import React from 'react';
import { makeStyles } from '@material-ui/styles';

import { useStyles } from './my-component.styles.js'; 

const myComponent = (props) => {
    const styleProps = { width: '100px', height: '100px' };
    const classes = useStyles(styleProps);

    return (
        <div className={classes.mySelector}></div> // with 100px and height 100px will be applied
    )
}

TypeScript示例:

my-component.ts

export const useStyles = makeStyles(theme => ({
    mySelector: props => {
        display: block,
        width: props.width,
        height: props.height,
    },
}));

my-component.interfaces.ts

import React, { FC } from 'react; 
import { makeStyles } from '@material-ui/styles';

import { useStyles } from './my-component.styles.ts'; 
import { MyComponentProps, StylesProps } from './my-component.interfaces.ts'; 

const myComponent: FC<MyComponentProps> = (props) => {
    const styleProps: StylesProps = { width: '100px', height: '100px' };
    const classes = useStyles(styleProps);

    return (
        <div className={classes.mySelector}></div> // with 100px and height 100px will be applied
    )
}

my-component.styles.ts

export interface StyleProps {
    width: string;
    height: string;
}

export interface MyComponentProps {
}

答案 2 :(得分:0)

我们通常有2种模式,您的 prop 变量是否导入到组件中。

  1. 如果导入了您的 prop 变量,则它是一个全局变量,因此在makeStyles()中有效:
     import {prop} from ...
    
     const useStyles = makeStyles((theme) => ({
       className:{
          // use prop
       }
     })
    
     define component...
  1. 如果在组件(例如状态)中定义了 prop 变量,则有两种选择:
  • 您可以将 prop 变量传递给makeStyles():

    const useStyles = makeStyles((theme,prop) => ({
      className:{
         // use prop
      }
    })
    
    define component...
  • 您可以使用箭头功能,而无需将任何参数(主题除外)传递给makeStyles():
    const useStyles = makeStyles((theme) => ({
      className:(prop)=>({
         //use prop
      })
    })

    define component...

答案 3 :(得分:0)

这里有一个例子,说明如何像 styled-components 一样使用 makeStyles() 只使用 props 或 props 和 theme

component.js

import { tableCellStyling } from './component.styled.js';

const RenderRow = (props) => {
    const { noPaddingTopBottom } = tableCellStyling(props);
    return(
        <StyledTableRow>
            {data.map( (row,i) => (
                <StyledTableCell className={noPaddingTopBottom}>
                    {row.data}
                </StyledTableCell>
            )}
        </StyledTableRow>
    )
};

假设我的 props 对象由 RenderRow 组件传递给 tableCellStyling,其中包含 { color: 'grey', thinRow: true }

component.styled.js

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

export const tableCellStyling = makeStyles(theme => ({
    noPaddingTopBottom: {
        borderBottom: ({ color }) => color ? `2px solid ${color}` : '2px solid red',
        paddingBottom: props => props.hasActions && 0,
        paddingTop: props => props.hasActions && 0,
        backgroundColor: theme.palette.common.white,
    },
}));