In the class component, the setState()
method can take a callback function, but in a functional component when I give a callback to costume setState this warning occurs:
Warning: State updates from the useState()
and useReducer()
Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect()
.
I need my state set, and then the page will redirect. But I don't have any idea.
Asked
Active
Viewed 1.2k times
13

S. Hesam
- 5,266
- 3
- 37
- 59
-
2The warning you are getting there is trying to give you the idea actually. You can use `useEffect` for this. – devserkan Nov 27 '19 at 07:39
-
1Hi, if you would like a more explicit answer feel free to share any code that is troubling you and we will be able to help better – JamesGill Nov 27 '19 at 07:43
-
What if your functional component remain class component? is there any special concern for that? – tareq aziz Nov 27 '19 at 07:43
-
@devserkan How can I useEffect for this situation? – S. Hesam Nov 27 '19 at 07:44
-
@tareqaziz I have to use functional components. – S. Hesam Nov 27 '19 at 07:46
-
@techguru I've already accepted it – S. Hesam Nov 29 '19 at 20:49
2 Answers
14
Instead of passing a callback
function, use useEffect
hook, and do something like this to achieve the desired result.
useEffect(() => {
console.log('state changed', your-state-variable)
// write your callback function here
}, [your-state-variable]);

S. Hesam
- 5,266
- 3
- 37
- 59

Guruprasad
- 753
- 6
- 23
0
Be careful! In a class component, you can call a callback function right after each setState
that you want, but in the functional component, the useEffect
hook run after any changing state that happens in the whole of your component.
To handle this challenge, you should be careful in choosing your state and how to set it.
This is a very simple example:
import { Grid, Button, Typography } from "@material-ui/core";
import { Component, useState, useEffect } from "react";
export const FunctionComponent = () => {
const [count, setCount] = useState(0);
const [background, setBackground] = useState("white");
useEffect(() => {
setTimeout(() => setBackground("white"), 100);
}, [background]);
const countIncreamentHandler = () => {
setCount((count) => count + 1);
setBackground("rgba(112, 181, 0, .2)");
};
const countDecreamentHandler = () => {
setCount((count) => count - 1);
setBackground("rgba(181, 9, 0, .2)");
};
return (
<Grid container justify="space-around">
<Button
variant="contained"
color="primary"
onClick={countIncreamentHandler}
>
+
</Button>
<Typography style={{ padding: 5, background }} variant="h5">
{count}
</Typography>
<Button
variant="contained"
color="secondary"
onClick={countDecreamentHandler}
>
-
</Button>
</Grid>
);
};
In class component:
export class ClassCompontet extends Component {
constructor() {
super();
this.state = {
count: 0,
background: "white"
};
}
countIncreamentHandler = () => {
this.setState(
(prevState) => ({
count: prevState.count + 1,
background: "rgba(112, 181, 0, .2)"
}),
() => {
setTimeout(() => {
this.setState({ background: "white" });
}, 100);
}
);
};
countDecreamentHandler = () => {
this.setState(
(prevState) => ({
count: prevState.count - 1,
background: "rgba(181, 9, 0, .2)"
}),
() => {
setTimeout(() => {
this.setState({ background: "white" });
}, 100);
}
);
};
render() {
return (
<Grid container justify="space-around">
<Button
variant="contained"
color="primary"
onClick={this.countIncreamentHandler}
>
+
</Button>
<Typography
style={{ padding: 5, background: this?.state?.background }}
variant="h5"
>
{this?.state?.count}
</Typography>
<Button
variant="contained"
color="secondary"
onClick={this.countDecreamentHandler}
>
-
</Button>
</Grid>
);
}
}

S. Hesam
- 5,266
- 3
- 37
- 59