Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass material-ui's theme object to defaultProps?

In React, I have a functional component that validates props and implements default props for any non-required props. I'm also using mui's makeStyles to grab the theme object to apply styling to my components.

My question is how does one go about passing the makeStyles theme object down to the defaultProps to avoid hard keying values?

import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';


const useStyles = makeStyles(theme => ({
  componentStyle: {
    color: `${theme.palette.light.main}`,  // just like how I'm accessing `theme` here, I'd like to access in `defaultProps`
  },
  componentContainer: ({ backgroundColor }) => {
    return { backgroundColor };
  },
}));


const Example = ({ backgroundColor }) => {
  const classes = useStyles({ backgroundColor });

  return (
    <div className={classes.componentStyle} >
      <div className={classes.componentContainer} /> // use default styling using `theme` if none is provided
    </div>
  )

}


Example.propTypes = {
  backgroundColor: PropTypes.string,
};


Example.defaultProps = {
  backgroundColor: `${theme.palette.light.main}`,  // I want to access `theme` here and do the following. While `backgroundColor: 'white'` will work I want to avoid hard keying values. 
};


export default Example;

EDIT: based on the solution provided by @Fraction below is what I'll move forward with.

import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';


const useStyles = makeStyles(theme => ({
  componentStyle: {
    color: `${theme.palette.light.main}`,
  },
  componentContainer: ({ backgroundColor }) => {
    return { 
      backgroundColor: backgroundColor || `${theme.palette.light.main}`
    };
  },
}));


const Example = ({ backgroundColor }) => {
  const classes = useStyles({ backgroundColor });

  return (
    <div className={classes.componentStyle} >
      <div className={classes.componentContainer} />
    </div>
  )

}


Example.propTypes = {
  backgroundColor: PropTypes.string,
};


Example.defaultProps = {
  backgroundColor: null, 
};


export default Example;
like image 791
Mix Master Mike Avatar asked Jan 20 '26 04:01

Mix Master Mike


1 Answers

I would suggest to not pass theme as prop, but to use Theme context.

I do that in all apps which I am working on and it is flexible and prevents props drilling as well.

In your top level component, e.g. App.tsx put the Material UI theme provider:

import { ThemeProvider } from '@material-ui/core/styles';
import DeepChild from './my_components/DeepChild';

const theme = {
  background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
};

function Theming() {
  return (
    <ThemeProvider theme={theme}>
      <DeepChild />
    </ThemeProvider>
  );
}

Then, in your components which need a theme: (as per https://material-ui.com/styles/advanced/#accessing-the-theme-in-a-component):

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

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

like image 175
Marek Urbanowicz Avatar answered Jan 21 '26 20:01

Marek Urbanowicz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!