In the class ponent, the setState()
method can take a callback function, but in a functional ponent 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 ponent body with useEffect()
.
I need my state set, and then the page will redirect. But I don't have any idea.
In the class ponent, the setState()
method can take a callback function, but in a functional ponent 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 ponent body with useEffect()
.
I need my state set, and then the page will redirect. But I don't have any idea.
-
2
The warning you are getting there is trying to give you the idea actually. You can use
useEffect
for this. – devserkan Commented Nov 27, 2019 at 7:39 - 1 Hi, 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 Commented Nov 27, 2019 at 7:43
- What if your functional ponent remain class ponent? is there any special concern for that? – tareq aziz Commented Nov 27, 2019 at 7:43
- @devserkan How can I useEffect for this situation? – S. Hesam Commented Nov 27, 2019 at 7:44
- @tareqaziz I have to use functional ponents. – S. Hesam Commented Nov 27, 2019 at 7:46
2 Answers
Reset to default 15Instead 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]);
Be careful! In a class ponent, you can call a callback function right after each setState
that you want, but in the functional ponent, the useEffect
hook run after any changing state that happens in the whole of your ponent.
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 ponent:
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>
);
}
}