ReactJS Invalid hook call while add useStyle variable - reactjs

I am trying to write a from but it throws me this 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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
This is App.js file where i am writing the form:
import React, { Component } from 'react';
import TextField from '#material-ui/core/TextField';
import './App.css';
import useStyles from '../src/styleMaker'
import { makeStyles } from '#material-ui/core/styles';
class App extends Component {
state = {
ssn: '',
}
useStyles = makeStyles(theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 200,
},
dense: {
marginTop: 19,
},
menu: {
width: 200,
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
button: {
margin: theme.spacing(1),
},
}));
classes = useStyles();
onHandleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
render() {
return (
<React.Fragment>
<form noValidate autoComplete="off">
<TextField
id=""
label="SSN"
value={this.state.ssn}
onChange={(event) => this.onHandleChange(event)}
type="number"
name='ssn'
margin="normal"
className={this.classes.textField}
/>
<TextField
id=""
label="SSN"
value={this.state.phone}
onChange={(event) => this.onHandleChange(event)}
type="number"
name='phone'
margin="normal"
className={this.classes.textField}
/>
</form>
</React.Fragment>
);
}
}
export default App;
Can anyone help me whats wrong with my code? Why my code is not working?
When i add userStyle, then i throws me the error, Can anyone help me in this case?
I spend hour to fix this issue but now i just give up on it. Anyone helps will make my day.. Thanks in advance

As the error is suggesting you
Hooks can only be called inside of the body of a function component
You are using a class based component here, you can convert this class based component to functional component, you would also need to use useState Hook for your state in functional Component, you can do this,
const App = () => {
const [ssn, setSsn ] = useState('')
const classes = useStyles()
// remaining code
return (
....
)
}
Also when you use functional component you cannot use this inside functional component
Hope it helps

You can not use hooks from within class based components. If you want to use hooks, you need to convert your components to functional, something along the following lines:
function App() {
const classes = useStyles();
...
return (
...
)
}

Related

MUI styled a Custom React Component from external lib does not work

I currently have a React component that is from a module (it is in node_modules folder):
type Props = {
someProps: any
};
export function ComponentA(props: Props) {
const [value, setValue] = React.useState("");
return (
<TextField
name="search-bar"
value={value}
label="Search"
/>
);
}
Then in my project, I want to styled in using styled from mui material and using theme:
import {ComponentA} from '..';
export const StyledComponent = styled(ComponentA)(({ theme }) => ({
width: 'auto',
height: '5%',
margin: '10px 15px 20px',
}));
Then finally use it like this:
<StyledComponent props={someProps: 1}/>
This however does not seem to work. Other styled components that were created in my project alone is working correctly. I wonder if I did it wrongly or missing something.
I was able to fix it with className props passed in component, as suggested in the comments.

How to use 'classes' to customize compound components in Mui?

I am trying to override the Mui styles by using the classes prop.
For example, I would like to override the InputLabel color of the TextField component.
I would like to use one definition of makeStyles that will set all css rules, starting at the root (TextField) and overriding whatever I want in the hierarchy (for example, the InputLabel when focused), when passing it to the component in the classes prop.
How is it done?
import * as React from "react";
import TextField from "#mui/material/TextField";
import makeStyles from "#mui/styles/makeStyles";
const useStyles = makeStyles({
root: {
color: "yellow",
label: {
color: "brown"
}
}
});
export default function Input() {
const classes = useStyles();
return (
<TextField
classes={classes}
id="outlined-basic"
label="Outlined"
variant="outlined"
/>
);
}
Answer
import * as React from "react";
import TextField from "#mui/material/TextField";
import makeStyles from "#mui/styles/makeStyles";
const useStyles = makeStyles({
root: {
"& .MuiInputBase-input": {
color: 'red',
padding: "0.2rem"
},
},
});
export default function Input() {
const classes = useStyles();
return (
<TextField
InputProps={{ classes }}
/>;
);
}
codesandbox
The classes prop in MUI gives you access to the CSS Rule Names for a component. When you're using this prop, check the API spec for that component. The CSS Rule Names are at the bottom of the page.
https://mui.com/api/text-field/#css
For this component, there is only 1 rule available (root), so this will (I think) have the same effect as just using className.
What you probably want to do is use the InputProps prop instead. The Input component has way more CSS Rules you can target: https://mui.com/api/input/#css
So, I think you probably want to do this:
<TextField
InputProps={{ classes }}
id="outlined-basic"
label="Outlined"
variant="outlined"
/>
EDIT to help answer comment:
I don't think you need to target InputBase, as I believe you can target input instead. To target the input CSS Rule, just change the root key to input:
import * as React from "react";
import TextField from "#mui/material/TextField";
import makeStyles from "#mui/styles/makeStyles";
const useStyles = makeStyles({
input: {
color: 'red',
padding: "0.2rem"
},
});
export default function Input() {
const classes = useStyles();
return (
<TextField
InputProps={{ classes }}
/>;
);
}
The CSS rules in the docs are sensitive to the keys in the object you pass.
The best way I found is to use the Mui v5 sx property.
(makeStyles is deprecated - https://mui.com/guides/migration-v4/#2-use-tss-react)
(input signifies the rule in https://mui.com/api/input-base/#css)
import * as React from "react";
import TextField from "#mui/material/TextField";
export default function Input() {
const classes = useStyles();
return (
<TextField
sx={{
"& input":
{ padding: "0rem",color: "blue" }
}}
/>
);
}

React Native: hooks can only be called inside of the body of a function component

code:
import React, { Component } from 'react'
import {
View,
Text,
TextInput
} from 'react-native'
export default class Home extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: 'Home'
}
}
render () {
const [value, onChangeText] = React.useState('Useless Placeholder');
return (<View>
<Text>Home</Text>
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={text => onChangeText(text)}
value={value}
/>
</View>);
}
}
Learning React Native, encountered this error, how to correct the above code?
The official example of my imitation: https://reactnative.cn/docs/textinput
You are using class component and hooks can only be used in functional components.
Either use setState or convert the class to functional, like so
export default const Home = props => {
// your code
}
Moreover, it is not a good idea to set state inside the render, so you should take it outside.

Invalid hook call

It looks like a common problem but I can't solve it. I'm using React, TypeScript and Material-UI. All together do not work if I'm using classes (that's what TS is for). Here is my minimal example that is not working:
File RTaskForm.tsx
import * as React from "react"
import {Task, TaskProcessor} from "./Task"
import { makeStyles, Grid, TextField } from '#material-ui/core'
const styles = makeStyles(theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
},
dense: {
marginTop: theme.spacing(2),
},
menu: {
width: 200,
},
}));
export class RTaskForm extends React.Component<
{prefix: string},
{task: Task}> {
constructor(props: any) {
super(props)
this.state = {
task: TaskProcessor.tasks(false)[1]
}
}
render() {
const classes = styles()
return (
<form className={classes.container} noValidate autoComplete="off">
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<TextField
required
id="filled-required"
label="Required"
defaultValue="Hello World"
className={classes.textField}
margin="normal"
variant="filled"
/>
</Grid>
</Grid>
</form>
)
}
}
File index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { RTaskForm } from "./RTaskForm"
ReactDOM.render(<div id="root">
<RTaskForm prefix="Hi"/>
</div>, document.getElementById('root'));
File Task.ts (only two classes to allow compiling)
export class Task extends Map<string, string> {
static emptyTask() {
return new Task()
}
}
export class TaskProcessor {
static tasks(b: boolean): Task[] {
return [Task.emptyTask()]
}
}
I know I have to use withStyles instead of makeStyles, but I have to provide a function parameter for theme, null is not accepted.
Happy to get some help, thanks.
Edit: In the browser I get this error message (line 36 marked):
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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See "cannot write the link here" for tips about how to debug and fix this problem.
3 stack frames were collapsed.
render
src/RTaskForm.tsx:36
33 | }
34 |
35 | render() {
36 | const classes = styles()
| ^ 37 | return (
38 | <form className={classes.container} noValidate autoComplete="off">
39 | <Grid container spacing={2}>
View compiled

WithStyles not working in Material UI for React

I have an app using Material UI Beta where I try to style a simple component as follows:
import { MuiThemeProvider } from 'material-ui/styles';
const styles = theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: 200,
marginRight: theme.spacing.unit,
width: 200,
},
menu: {
width: 200,
},
});
export const CreateJob = (props) => {
const { classes } = props;
let confirmDelete = () => {
const r = window.confirm("Confirm deletion of job");
return r === true;
};
return (
<MuiThemeProvider>
<div>
<form onSubmit={props.isEditting ? props.handleEdit : props.handleSubmit} noValidate autoComplete="off">
<h2>Update job details</h2>
<TextField
error={props.jobIdError !== ''}
helperText={props.jobIdError || "Example: ES10"}
autoFocus
margin="dense"
id="jobId"
label="Job ID"
name="jobid"
fullWidth
onChange={props.handleInputChange('jobId')}
value={props.jobId} />
</form>
</div>
</MultiThemeProvider>
I then use this in my parent component as follows:
<CreateJob open={this.state.open} />
However, this yields the following error:
TypeError: Cannot read property 'classes' of undefined
this.state is not defined in your code. In the example, state is defined as
state = {
name: 'Cat in the Hat',
age: '',
multiline: 'Controlled',
currency: 'EUR',
};
Sorry I'm kinda late with an answer, but I just found this question while searching for another solution.
I'm going to assume you also imported withStyles.
Firstly, you don't need to export both the simple component and the enhanced one:
export const CreateJob = props => {...} // lose the 'export'
export default withStyles(styles)(CreateJob); // only export here
Secondly, a real problem: <MuiThemeProvider> should be placed around your highest component(usually the <App> component that you render in your entry point file), so you can customize the default theme to your liking for the whole app; see their example here. I'm not sure, but this might even solve your problem, since that should have thrown another error like in this issue.
I just hope this helps someone, but I cannot be sure about what your exact problem is without the complete component file.

Resources