Method replacements for material ui v4 to v5 upgrade - reactjs

I'm currently migrating from v4 to v5, but it appears #material-ui/core/styles/colorManipulator wasn't carried over or is accessible differently. I tried to find info about it in the docs and migration guide but didn't see anything. Is there an alternative that should be usied to access methods such as darken()? also i'm looking for the alternative to getting styles from things i.e. import { styles as FabStyles } from "#material-ui/core/Fab/Fab"; in v5. I don't see away to access the individual styles now.

darken, lighten, alpha, and other functions accessed via #material-ui/core/styles/colorManipulator in v4 are exported from #mui/material/styles in v5.
Though the migration guide doesn't explicitly mention it, at least some cases of this are handled by the preset-safe codemod (specifically the core-styles-import codemod).
Here's an example usage of darken in v5:
import { darken } from "#mui/material/styles";
export default function App() {
return (
<div>
<h1 style={{ color: "#f00" }}>#f00</h1>
<h1 style={{ color: darken("#f00", 0.25) }}>darken("#f00", 0.25)</h1>
</div>
);
}
As far as the last portion of your question, the styles for each component are no longer exported separately and cannot be leveraged independent of the component.

Related

Material-UI ThemeProvider overwrites styles globally instead of only for wrapped components

I have a React Component with multiple Material-UI Selects. Now I wanted to overwrite some styles of one of them so I created a theme and now want to apply it wit the ThemeProvider.
My problem is that the ThemeProvider overwrites the styles of every Select and not only of the one it is wrapped around.
When googling I found a lot of questions how to make ThemeProvider apply its overwrites globally but that is the opposite of what I am trying to do. I want the ThemeProvider to apply its overwrites only to the Components, that it wraps around.
Is there a better alternative to using ThemeProvider in my usecase? If yes, it has to work with class based Components (because I am using one here)
Codesandbox that shows my problem: https://codesandbox.io/s/twilight-sun-vyl9i
I am fairly new to Material-UI, so forgive me if I do something fundamentally wrong.
I had the same problem in V4 and had to resolve it another way.
The parent <ThemeProvider> with no theme prop solution wouldn't work with Typescript because the theme prop is required.
If anyone needs a solution that works with Typescript, I resolved it using StylesProvider. By wrapping each ThemeProvider in a StyleProvider with a different seed, your theme will no longer interfere with any other components outside of the StyleProvider.
Like so
import { ThemeProvider, StylesProvider } from '#material-ui/core/styles';
//...
<StylesProvider generateClassName={generateClassName}>
<ThemeProvider theme={theme}>
<children>
</ThemeProvider>
</StylesProvider>
You'll want to create a generateClassName prop to pass in:
import { createGenerateClassName } from '#material-ui/core';
const generateClassName = createGenerateClassName({
seed: 'blue-select,
});
export default generateClassName;
OK, I found the solution myself. According to this issue on the material-ui github , there is a v4 bug that multiple ThemeProviders must have a parent ThemeProvider element. According to them it will be fixed in the upcoming v5.
So what I did, I just wrapped a <ThemeProvider> around my <div className="App"> without giving it a theme prop.

Styled components - Correct way of approach

I am using styled components in my project.
Consider the following piece of code
import { Footer, FooterLeft, FooterRight, NavLink } from './footer_styles';
const FooterView = ({ prop }) => (
<Footer className="row">
<FooterLeft>
©Sample company, LLC
</FooterLeft>
<FooterRight>
<NavLink to="#" className="footer-link">Privacy Policy</NavLink>
<span className="separator"> | </span>
<NavLink to="#">Terms & Conditions</NavLink>
</FooterRight>
</Footer>
);
So i have the following questions.
1) Can i use bootstrap classes in styled components like what is shown in the code? Is this the correct approach? If not, how to use bootstrap styles along with styled components?
2) Do i need to create a component for each element in dom? For example, in the code that is shown, there is a span tag with class name "separator" for which the styles are added as follows
export const FooterRight = styled.div`
.separator {
float: left;
}
.footer-link {
margin-left: 0px;
}
`;
Is this approach correct? or
Do i need to create a separate component for separator?
I am a bit confused here. Any help would be appreciated.
You can use bootstrap class for style your component, it is nothing wrong. But it better if you use the React Bootstrap, library optimize for React. For example, the drop-down button you can use bootstrap class because it will use Jquery to execute the animation. But you shouldn't do it because Jquery manipulates the real DOM, React manipulate the virtual DOM so it is not good for performance.
You can read more here: https://reactjs.org/docs/integrating-with-other-libraries.html
The answer still yes, with the class to style the component, should use it to reduce the time for coding, with anything related to Jquery, just use the React Component.
I suggest you use the reactstrap, pretty similar to Bootstrap: https://reactstrap.github.io
Another thing, there is many ways to style component, but I am using CSS module, just need to create a CSS file with add-on module of the file name like this:
styleComponent.css --> styleComponent.module.css
And then import to your project:
import styles from './styleComponent.module.css'
And then you can style your component with normal css:
<div className={styles.separator} > Hello World </div>
In styleComponent.module.css:
.separator{
height: 20px;
background: black;
}
.separator:hover{
background: white;
}
It is more easy to manage your project because every single component it has a CSS file to go with it and the className is unique mean locally, Webpack will automatically convert the className 'separator' to '2djfas_separator' that will solve your problem with naming class in CSS.
Hope it helps a little bit for your project!!!

Material UI css load order

I am having hard time understanding how I should structer my project.
I am using react with material UI and css modules.
Problem is that god knows why, all styling from MUI loads at the bottom of the header same as css module styling.
After some research I found two solutions:
Use !important inside css modules which is terrible.
Changing the injection order https://material-ui.com/guides/interoperability/#css-modules
Problem with the second one is that it would be terrible tedieouse in a multi component project where every time you introduce a new component you have to load it manually as in the example. Am I missing something obvious? Do you have any ideas how to easier change the load order?
According to the Material-UI documentation, you should add a <StylesProvider/> component, which wraps your component tree.
import { StylesProvider } from '#material-ui/core/styles';
<StylesProvider injectFirst>
{/* Your component tree.
Styled components can override Material-UI's styles. */}
</StylesProvider>
If injectFirst is set (and true of course), the Material UI style tags will be injected first in the head (less priority)
I think you may be misunderstanding something in the example. There isn't anything you need to do on a per-component basis to change the load order.
The steps are as follows:
1. In your index.html add a comment like <!-- jss-insertion-point --> into the head where you would like the jss CSS to be inserted.
2. In your index.js (or somewhere at or near the top of your rendering hierarchy) create the jss configuration to indicate the name of the insertion point comment:
import JssProvider from "react-jss/lib/JssProvider";
import { create } from "jss";
import { jssPreset } from "#material-ui/core/styles";
const jss = create({
...jssPreset(),
// We define a custom insertion point that JSS will look for injecting the styles in the DOM.
insertionPoint: "jss-insertion-point"
});
3. Wrap your top-level element in the JssProvider to put those configurations in play (no component-specific steps):
function App() {
return (
<JssProvider jss={jss}>
<div className="App">
<Button>Material-UI</Button>
<Button className={styles.button}>CSS Modules</Button>
</div>
</JssProvider>
);
}
I've created a CodeSandbox similar to the one pointed at by the Material-UI documentation except that this one uses the create-react-app starting point, so the dependencies are simpler.
In version 5 MUI changed the import and some components became deprecated.
By default, the style tags are injected last in the <head> element of the page. They gain more specificity than any other style tags on your page e.g. CSS modules, styled components.
Not in the documentation, but the StyledEngineProvider component has an injectFirst prop to inject the style tags first in the head (less priority):
<StyledEngineProvider injectFirst>
<MUIThemeProvider theme={theme}>
{children}
</MUIThemeProvider>
</StyledEngineProvider>

How to use styled-components theme in Gatsby 2.0

so as the title says I'm curious what is the best practise of adding a styled-components theme to Gatsby website? I've been searching through the internet without finding a definite answer but from what I've gathered I probably should do it by creating a layout in src/layouts/index.tsx that wraps all the pages with the ThemeProvider:
import * as React from 'react'
import { ThemeProvider } from 'styled-components'
import { defaultTheme } from '../theme/defaultTheme'
export const DefaultLayout = ({ children }) => (
<ThemeProvider theme={defaultTheme}>
{ children }
</ThemeProvider>
)
And then I'm able to use theme freely in my styled components? Which doesn't work and I'm getting a bit frustrated with this.
Ok well the solution was simple. Since I was following the old examples done with v1 I guess I should have known that the layouts are not automatically added in v2. Sigh so that layout works but I just have to add it manually:
import { DefaultLayout } from '../layouts/DefaultLayout'
...
<DefaultLayout>
<div>
<h1>Front page</h1>
<Button>I am a button</Button>
</div>
</DefaultLayout>
Hmmph frustrating bug but maybe that was on me.

Material-UI #next Does not support props-based styling?

With the arrival of Material-UI#next comes the replacement of LESS-based styling with CSS-to-JS-based styling. However, the component demos on Material-UI's website appear to ignore the creation of props-based-styling. I'm trying to create divs containing various Material-UI components at specific absolute heights on my page, however, the requirement of the stylesheet being predefined outside of the class means that the properties within the stylesheet can't be based on props passed to the component. Am I missing something?
For example:
import React, {Component} from 'react';
import {withStyles, createStyleSheet} from 'material-ui/styles';
import Button from 'material-ui/Button';
const styleSheet = createStyleSheet({
container: {
position: "absolute",
top: /*How can this be dependent upon the props passed to the component?*/,
height: /*How can this be dependent upon the props passed to the component?*/,
}
});
class Foo extends Component {
render() {
let classes = this.props.classes;
return (
<div className={classes.container}>
<Button raised/>
</div>
);
}
}
export default withStyles(styleSheet)(Foo);
The example component displayed above can't have props-dependent styles, because props is not defined when the stylesheet is created. So how do I solve this problem? IS there a solution?
I would strongly advise you check out Styled Compoments. They make styling very simple and even allow you to pass third party components (in your case Material UI components). They also allow you to pass in props like the following:
const Stylesheet = styled.div`
color: ${props => props.primary ? 'white' :
`
<Stylesheet primary>My Div</Stylesheet>
Check out the docs for more details, that was a very simple example, but they are super easy to work with and you can accomplish exactly what you need with them.

Resources