在Material UI中将变量发送给withStyles?

时间:2019-02-22 18:03:39

标签: css reactjs material-ui wrapper higher-order-components

我有以下内容:

class StyledInput extends React.Component{


  styles = (color, theme) => ({
    underline: {
      borderBottom: `2px solid ${color}`,
      '&:after': {
        borderBottom: `2px solid ${color}`,
      }
    }
  })

  div = props => (
    <TextField
    placeholder="temp input"
    InputProps={{
      classes:{
        root: props.classes.underline
      },
      style:{
        height: '1.5rem',
        fontSize:'1rem',
        marginTop: '-1rem',
      }
    }}
    >
      <div>
        {props.children}
      </div>
    </TextField>
  )

  Styled = withStyles(this.styles('white'))(this.div)

  render(){
    return(
      <div>
        <this.Styled>{this.props.children}</this.Styled>
      </div>
    );
  }
}

export default StyledInput;

因此,它的作用是成功地获取了一个实质性的UI文本字段,并在用户单击该字段时将底部栏更改为白色,而不是蓝色。大!

...但是...

我真的想做的是

<this.Styled color={someDefinedColor}>{this.props.children}</this.Styled>

Styled如下所示:

Styled = (color) => withStyles(this.styles(color))(this.div)

,以便我可以将颜色动态传递给Styled属性。显然,这是伪代码-我一直在使用它,但无法通过它。一般来说,material-ui会动态更改颜色,这真让人讨厌,所以我想知道是否有人知道如何使它起作用。

谢谢!

解决方案 ...虽然不好。

我不确定如何将伪元素与makeStyles和功能组件一起使用,但这是一种对我有用的解决方案。在后人将其添加到这里,以防其他人发现它有用:

class StyledInputInner extends React.Component{

  styles = (color, theme) => ({
    underline: {
      '&:before': {
        borderBottom: `2px solid ${color}`,
      },
      '&:after': {
        borderBottom: `2px solid ${color}`,
      },
      '&:hover:not($disabled):before': {
        backgroundColor: `2px solid ${color}`
      },
      '&$focused:after': {
        borderBottom: `2px solid ${color}`
      },
    }
  })  

  textField = props => (
    <TextField
    placeholder="temp input"
    InputProps={{
      classes:{
        root: props.classes.underline
      },
      style:{
        height: '1.5rem',
        fontSize:'1rem',
        marginTop: '-1rem',
      }
    }}
    onClick={()=>this.props.onClick()}
    onChange={(evt)=>{this.props.onChange(evt)}}
    >
      <div>
        {props.children}
      </div>
    </TextField>
  )

  StyledTextField = withStyles(this.styles(this.props.color))(this.textField)

  render(){
    return(
      <div>
        <this.StyledTextField>{this.props.children}</this.StyledTextField>
      </div>
    );
  }
}

class StyledInput extends Component {
  render(){
    return(
      <MainContext.Consumer>
      {stateData => {
        return(
          <StyledInputInner 
          color={stateData.state.InputColor}
          onChange={(evt)=>this.props.onChange(evt)}
          onClick={this.props.onClick}
          > 
            {this.props.children} 
          </StyledInputInner>
        )      
      }}
      </MainContext.Consumer>
    )
  }
}

export default StyledInput;

2 个答案:

答案 0 :(得分:2)

以下是使用新的hook syntax来执行此操作的示例:

index.js

import React from "react";
import ReactDOM from "react-dom";
import StyledComponent from "./StyledComponent";
const CustomComponent = ({ children, className }) => {
  return (
    <p className={className}>
      Just showing passing in the component to use rather than automatically
      using a div.
      <br />
      {children}
    </p>
  );
};
function App() {
  return (
    <div className="App">
      <StyledComponent color="green">
        Here's my content with green underline
      </StyledComponent>
      <StyledComponent
        component={CustomComponent}
        color="blue"
        hoverColor="orange"
      >
        Here's my content with blue underline that changes to orange on hover.
      </StyledComponent>
    </div>
  );
}

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

StyledComponent.js

import React from "react";
import { makeStyles } from "@material-ui/styles";
const useStyles = makeStyles({
  root: {
    borderBottom: ({ color }) => `2px solid ${color}`,
    "&:hover": {
      borderBottom: ({ color, hoverColor }) => {
        const borderColor = hoverColor ? hoverColor : color;
        return `2px solid ${borderColor}`;
      }
    }
  }
});

const StyledComponent = ({
  component: ComponentProp = "div",
  children,
  color,
  hoverColor
}) => {
  const classes = useStyles({ color, hoverColor });
  return <ComponentProp className={classes.root}>{children}</ComponentProp>;
};

export default StyledComponent;

Edit useStyles with variable

如果需要,可以将此useStyles方法放在其自己的文件中,并将其重新用作自定义钩子,以使其生成的类(仍具有可变支持)可用于多个组件(而不只是StyledComponent

答案 1 :(得分: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,
    },
}));