Custom React Component styles being overwritten by Material-UI style

天大地大妈咪最大 提交于 2020-03-05 03:14:15

问题


RELATED QUESTION OVER AT: Styles being overwritten by Material-UI style

I am create a component library on top of Material UI. Using JSS I'd like to be able to pass in styles to my custom components. However, I'm having issues with material-ui's root styles having higher specificity than what I'm passing in. I have tried overwriting the material-ui components default styles with the classes syntax but it simply creates another class with a similar name and higher specificity (makeStyles-root-51).

Consuming Custom Component:

import React from 'react';
import {gSelect} from 'g-react-component-library/dist'
import {createUseStyles} from 'react-jss'

const useStyles = createUseStyles({
    gSelect: {margin: "15px"},
    example: {float: "left", display: "inline-block", whiteSpace: 'nowrap', verticalAlign: 'top'}
});

function App() {

    const classes = useStyles();
    return (
        <div className={classes.example}>
            <div className={classes.separator}>
                <div>Selects:</div>
                <gSelect default={1} classes={{gSelect: classes.gSelect}} callback={(e)=>{console.log(`${e} selected`)}} options={[1,2,3,4]}/>
                <gSelect default={'One'} classes={{gSelect: classes.gSelect}} callback={(e)=>{console.log(`${e} selected`)}} options={["One", "Two", "Three", "Four"]}/>
            </div>
        </div>
    );
}

export default App;

The Actual Custom Component:

import React, {useState} from 'react';
import {Button, Select, FormControl, MenuItem, InputLabel} from '@material-ui/core'
import {makeStyles} from '@material-ui/styles'
import PropTypes from 'prop-types'

const gSelect = (props) => {

    const [value, setValue] = useState();

    const handleChange = event => {
        props.callback(event.target.value);
        setValue(event.target.value);
    };

    const useStyles = makeStyles({
        select: {
            border: 'solid #33333366 1px',
            color: 'rgba(51, 51, 51, 0.66)',
            fontWeight: '700',
            backgroundColor: 'white',
            outline: 'none',
            borderRadius: '5px',
            textAlign: 'left',
            width: '300px',
            position: 'relative',
        },
        root: {

        }
    });

    const classes = useStyles(props);
    return (
        <FormControl classes={{root: classes.gSelect}}>
        <InputLabel id="demo-simple-select-label">{props.default}</InputLabel>
        <Select value={value} onChange={handleChange} className={classes.select}>
            {props.options.map((option, index) => {
                return <MenuItem key={`${option}_${index}`} value={option}>{option}</MenuItem>
            })}
        </Select>
        </FormControl>
    )
};

gSelect.propTypes = {
    callback: PropTypes.func.isRequired,
    options: PropTypes.array.isRequired,
    default: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number
    ]).isRequired,
    disabled: PropTypes.bool,
    width: PropTypes.string
};

module.exports = {
    gSelect
};

回答1:


You're doing it wrong. GSelect should receive classes like this:

In App:

<GSelect default={1} classes={{gSelect:classes.gSelect}} callback={(e)=>{console.log(`${e} selected`)}} options={[1,2,3,4]}/>

Then in GSelect:

const useStyles = createStyles(...your styles); // call this hook factory outside your render

const GSelect = props => {
   const classes = useStyles(props) <- props contains an object called classes with a property gselect that gets merged into yours

   <Select value={value} onChange={handleChange} classes={{root:classes.gSelect}}>
}

EDIT: As for my original comment about creating your hook outside of your component, I meant do this:


// move this outside of your render
    const useStyles = createUseStyles({
        gSelect: {margin: "15px"},
        separator: {marginTop: "15px"},
        example: {float: "left", display: "inline-block", whiteSpace: 'nowrap', verticalAlign: 'top'}
    });

function App() {
    // use it inside of your render
    const classes = useStyles();
    ...
}

Read through this section and the following two, after a while, it'll click: https://material-ui.com/styles/advanced/#overriding-styles-classes-prop




回答2:


The solution to passing in styles to a custom component in the end was very simple. While @Adam answered my question the way it was worded, the solution I ended up with is as follows:

Consuming Custom Component:

import React from 'react';
import {gSelect} from 'g-react-component-library/dist'
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles ({
    gSelect: {margin: "15px"},
    example: {float: "left", display: "inline-block", whiteSpace: 'nowrap', verticalAlign: 'top'}
});

function App() {

    const classes = useStyles();
    return (
        <div className={classes.example}>
            <div className={classes.separator}>
                <div>Selects:</div>
                <gSelect default={1} className={classes.gSelect} callback={(e)=>{console.log(`${e} selected`)}} options={[1,2,3,4]}/>
                <gSelect default={'One'} className={classes.gSelect} callback={(e)=>{console.log(`${e} selected`)}} options={["One", "Two", "Three", "Four"]}/>
            </div>
        </div>
    );
}

export default App;

Fixes Above Include :

  • switched createUseStyles to makeStyles from @material-ui/core/styles
  • used className={classes.gSelect} instead of classes={{root: ...}}

The Actual Custom Component:

import React, {useState} from 'react';
import {Button, Select, FormControl, MenuItem, InputLabel} from '@material-ui/core'
import {makeStyles} from '@material-ui/styles'
import PropTypes from 'prop-types'

const gSelect = (props) => {

const [value, setValue] = useState();

const handleChange = event => {
    props.callback(event.target.value);
    setValue(event.target.value);
};

const useStyles = makeStyles({
    select: {
        border: 'solid #33333366 1px',
        color: 'rgba(51, 51, 51, 0.66)',
        fontWeight: '700',
        backgroundColor: 'white',
        outline: 'none',
        borderRadius: '5px',
        textAlign: 'left',
        width: '300px',
        position: 'relative',
    }
});

const classes = useStyles();
return (
    <FormControl className={props.className}>
    <InputLabel id="demo-simple-select-label">{props.default}</InputLabel>
    <Select value={value} onChange={handleChange} className={classes.select}>
        {props.options.map((option, index) => {
            return <MenuItem key={`${option}_${index}`} value={option}>{option}</MenuItem>
        })}
    </Select>
    </FormControl>
)
};

gSelect.propTypes = {
    callback: PropTypes.func.isRequired,
    options: PropTypes.array.isRequired,
    default: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number
    ]).isRequired,
    disabled: PropTypes.bool,
    width: PropTypes.string
};

module.exports = {
    gSelect
};

Fixes Above Include :

  • used className={props.className} on <FormControl>


来源:https://stackoverflow.com/questions/60119419/custom-react-component-styles-being-overwritten-by-material-ui-style

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!