I'm getting the following error after upgrading to MUI v4.0.2 from v3.9.x:
You must pass a component to the function returned by connect. Instead received {"propTypes":{},"displayName":"WithStyles(MyComponent)","options":{"defaultTheme":{"breakpoints":{"keys":["xs","sm","md","lg","xl"],"values":
...
MyComponent:
import { withStyles } from '#material-ui/core/styles'
const getStyles = theme => ({
fooBar: {
...
},
})
...
export default withStyles(getStyles)(MyComponent)
MyContainer:
import { connect } from 'react-redux'
import MyComponent from './MyComponent'
...
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
How to migrate withStyles?
Version 5.0.7 and earlier of react-redux performed the following validation on the component passed to connect:
https://github.com/reduxjs/react-redux/blob/v5.0.7/src/components/connectAdvanced.js#L91
invariant(
typeof WrappedComponent == 'function',
`You must pass a component to the function returned by ` +
`${methodName}. Instead received ${JSON.stringify(WrappedComponent)}`
)
With the introduction of React.forwardRef (which is used heavily in Material-UI v4) and other features introduced in React 16.8 (hooks), it is possible to have a component type that is not a function.
More recent versions of react-redux instead use isValidElementType from the react-is package. This correctly recognizes the component types returned by forwardRef and other methods.
I believe versions 5.1 and later of react-redux should all work fine without erroneously causing the error mentioned in the question.
This is how I do it:
import { withStyles } from '#material-ui/core/styles';
Define your styles object: look at the material-ui examples for guidance
const styles => ({
root: {
display: 'flex',
}
});
Then export the component using your styles:
export default withStyles(styles)(YourComponent);
Related
I am trying to import my jss file to React component (.jsx) and I have this error :
I looked through related questions and I tried all solutions, mostly about updating versions of material-ui. Here is my package.json file:
the way I write jss file :
import { makeStyles } from '#material-ui/styles';
const useStyles = makeStyles((theme) => ({
root:
{
margin: '10px'
}
}));
export default useStyles;
And jsx file :
import React from 'react';
import DateBar from './DateBar';
import Grid from '#material-ui/core/Grid';
import useStyles from './Board.jss';
export default function Board()
{
const classes = useStyles();
return(
...
Am I missing something or Do I need additional packages for using jsx and jss in React?
I have been trying all the solutions but didn't work..
Note: When I put the code inside of Jss into Jsx file, code works fine. Importing/Exporting might be an issue..
Edit: Still couldn't fix even though I created a new app and installed dependancies from the beginning..
I'm new to react and I'm trying to using makestyles and this is how :
in Header.jsx :
import React from "react";
import UseStyles from "./Header_style";
function Header() {
const classes =UseStyles();
return (
<div className={"Main-Header"}>
<div className={"Header-Logo"}>
<div className={classes.test}>test</div>
</div>
</div>
);
};
export default Header;
and style.js :
import {makeStyles} from '#material-ui/styles';
const UseStyles = makeStyles(theme=>({
test: {
backgroundColor: '#BDC3C7',
color :'red !important',
widtH : '18%'
},
}));
export default UseStyles;
but I'm getting folwing error:
×
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
*edit:
This is how I'm using Header :
import React, { Component } from 'react'
import Header from './component/heder/Header.jsx';
class App extends Component {
constructor() {
super();
this.state = {
monsters: [],
searchField: ''
};
}
render() {
return (
<Header/>
);
}
}
export default App;
and another thing, I'm getting following error too :
When you place your Header component in the return or render of a parent component make sure you use <Header /> and not {Header}
additionally if that's not the problem you can check this link which is the official react thread on that error.
Also posting how you render the component that is throwing the error would be very helpful.
Edit* Additionally you don't need to call makeStyles with a function. Since you are not using the theme, you can just call makeStyles with an object like this
const useStyles = makeStyles({
test: {
background: 'white',
width: '100%'
}
});
EDIT and additional answers:
Here's a snippet from MUI's official page on styles:
The way you import makeStyles:
import { makeStyles } from '#material-ui/styles
If you import this way you have to have applied the #material-ui/styles module.
If instead in your package.json you use '#material-ui/core and haven't installed #material-ui/styles you could be getting that error because you don't have the module #material-ui/styles.
If you just have #material-ui/core you can still import makeStyles without installing the standalone #material-ui/styles it is all included in #material-ui/core.
Simply import it like this instead:
import { makeStyles } from '#material-ui/core/styles'
everybody, I've found the solution!
have to use withStyles.
This question already has answers here:
Internal implementation of "makeStyles" in React Material-UI?
(2 answers)
Closed 1 year ago.
I just started learning React material-ui and I found this makeStyles function, and they said it returns a Hook.
I remember from React hooks that a custom hook is made by wrapping a built-in hook. I tried looking inside makeStyles, and it has some interoperability and some css-in-javascript pattern.
I am really fed up with rules coming over and over again. For now can someone please tell me what is this makeStyle function and perhaps suggest a better approach to reading about material-ui.
Thank you good people of Stack Overflow.
If you are familiar with the older version of Material-UI, you might have used withStyles, to use your custom styles in MUI components.
withStyles is just a HOC(Higher Order Component), used as a wrapper, to assign the classes prop to your component. You can furthur use the classes object to assign specific classes to your DOM or MUI elements in your component.
makeStyles is just a successor, which returns a hook(to access the custom classes). Now this is only a modern-react way of doing things in order to avoid HOCs.
MUI v3.9.3
import { withStyles } from '#material-ui/core/styles';
const styles = {
root: {
backgroundColor: 'red'
},
};
class MyComponent extends React.Component {
render () {
return <div className={this.props.classes.root} />;
}
}
export default withStyles(styles)(MyComponent);
MUI v4.9.5
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
backgroundColor: 'red'
},
});
export default function MyComponent(props) {
const classes = useStyles(props);
return <div className={classes.root} />;
}
When I upgrade v4, I get errors:
Uncaught (in promise) Invariant Violation: You must pass a component to the function returned by connect. Instead received {"propTypes":{},"displayName":"WithStyles(EditDialog)",...}
I tried to view the version of react-redux according to the I'm getting error after upgrading to Material UI 4 - withStyles method:
$ npm view react-redux version
7.1.0
Obviously, our situation is different.
It should be noted that my project is written using class component, so maybe this is the reason?
Is there any way to help me locate the problem?
----- Apend --------------
I'm use umi framework, And this is my code:
account/index.js
import React from 'react';
import { connect } from 'dva';
import { withStyles } from '#material-ui/core';
import styles from '#/utils/pageLayout';
...
import DetailDialog from './components/DetailDialog';
import EditDialog from './components/EditDialog';
class Index extends React.Component {
...
}
function mapStateToProps(state) {
const { list } = state.account;
return {
list
};
}
export default connect(mapStateToProps)(withStyles(styles)(Index));
account/components/DetailDialog.js
import React from 'react';
import { connect } from 'dva';
import { withStyles } from '#material-ui/core';
import styles from '#/utils/pageLayout';
...
class DetailDialog extends React.Component {
...
}
DetailDialog.propTypes = {
open: PropTypes.bool,
...
};
function mapStateToProps(state) {
const { list } = state.account;
return {
list
};
}
export default connect(mapStateToProps)(withStyles(styles)(DetailDialog));
account/components/EditDialog.js
import React from 'react';
import { connect } from 'dva';
import { withStyles } from '#material-ui/core';
import styles from '#/utils/pageLayout';
...
class EditDialog extends React.Component {
...
}
EditDialog.propTypes = {
open: PropTypes.bool.isRequired,
};
EditDialog.defaultProps = {
open: false,
};
function mapStateToProps(state) {
const { list} = state.account;
return {
list,
};
}
export default connect(mapStateToProps)(withStyles(styles)(EditDialog));
#/utils/pageLayout.js
const styles = theme => ({
r: {
height: '100%',
},
...
});
export default styles;
I see that you are importing connect from 'dva'. Unless you are using a beta version, the latest version of dva is 2.4.1 which includes react-redux as a dependency (not a peer dependency) and it is using "react-redux": "5.0.7". This will then have the exact same problem as the question you linked to.
This means you probably have two versions of react-redux in play (and likely two versions of redux as well), one included directly in your own package.json and one pulled in by dva.
Your main options would be to upgrade dva to its most recent beta version (currently 2.6.0-beta.12) or import connect from react-redux instead of dva.
I don't know anything about dva, so I have no idea what shape the beta is in, but given that it is the 12th beta, I would guess it is pretty close to a stable release.
If you are consistently importing redux/react-redux pieces from dva, then you may want to consider removing react-redux and redux from your own package.json to avoid duplicating them with different versions.
I have a React component written in TypeScript which applies the Material-UI style to react-select as shown below.
const styles = (theme: Theme) => createStyles({
});
export interface Props<TI> extends WithStyles<typeof styles, true> {
innerProps: Partial<AsyncSelectProps<TI>>;
selectRef?: React.RefObject<StateManager<TI>>;
onSelectionChange?: (selection: TI | undefined) => void;
}
class MaterialReactSelect<TI> extends React.PureComponent<Props<TI>> {
...
}
export default withStyles(styles, {withTheme: true})(MaterialReactSelect);
How can I modify this so that it's exported as a parameterized type so can be used as
<MaterialReactSelect<string>
selectRef={this.selectRef}
onSelectionChange={this.onSelectionChange}
innerProps={innerProps}
/>
rather than
<MaterialReactSelect
selectRef={this.selectRef}
onSelectionChange={this.onSelectionChange}
innerProps={innerProps}
/>
This is unfortunately not an issue with material-ui specifically but higher-order components in general. When using a higher-order component your're losing all generic type information of the wrapped component.
You should be able to observe the same issues with connect from react-redux or styled from styled-components.