Reputation: 6603
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.
Upvotes: 14
Views: 12613
Reputation: 783
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]);
Upvotes: 15
Reputation: 6603
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>
);
}
}
Upvotes: 0