每次更新props
后尝试重定向时,都会出现此错误:
警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。
已经尝试过:
React.useEffect(() => {
if (props.user) {
props.history.push("/admin/me");
}
}, [props.user]);
这(直接在render方法中):
if (props.user) {
return <Redirect to="/admin/me" />
}
不知道为什么卸载组件后redux会触发更新。我认为这就是问题所在。
如何在卸载组件之前退订Redux更新?
[编辑]
这是有问题的组件
export interface Props extends WithStyles<typeof styles>, RouteComponentProps, React.StatelessComponent, InjectedNotistackProps {
enqueueSnackbar: (a: any, b: any) => any;
login: (u: User) => any;
auth: AuthState;
api: ApiManager;
};
const LoginPage = (props: Props) => {
const { classes } = props;
const api = props.api;
const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState("");
const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!email || !password) {
return;
}
const user = new User({ email, password });
props.login(user)
.then(function success(resp: User) {
api.setToken(resp.token);
});
}
React.useEffect(() => {
if (props.auth.user && props.auth.user.token) {
// return <Redirect to="/profile/me" /> This does not work here...
props.history.push("/profile/me");
}
}, [props.auth.user]);
return (
<main className={classes.main}>
<CssBaseline />
<form className={classes.form} onSubmit={onSubmit}>
<Input onChange={e => setEmail(e.target.value)} name="email" />
<Input onChange={e => setPassword(e.target.value)} name="password" />
<Button type="submit">
Sign in
</Button>
</form>
</main>
);
}
const stateToProps = (state: AppState) => ({
auth: state.auth || { token: undefined, user: null }
});
const actionToProps = (dispatch: Dispatch) => ({
login: (user: User): Promise<User> => {
dispatch(createLoginStartAction("start"));
return user.login()
.then(function (loggedInUser: User) {
// This seems to be dispatched after the redirect or something!
dispatch(createLoginSuccessAction(loggedInUser));
return loggedInUser;
});
}
});
export default connect(stateToProps, actionToProps)(
withStyles(styles)(
withSnackbar(LoginPage)
)
);
事实证明它确实重定向了,问题在于它可以重新登录。为什么!?!?
答案 0 :(得分:0)
这可能是一种反模式,但是我过去常常这样解决这个问题。
在您班级的constructor
中,像这样重新分配setState
函数
const originSetState = this.setState.bind(this);
this.setState = ( ...args ) => !this.isUnmounted&&originSetState(...args);
然后在componentWillUnmount
中将布尔值设置为true,以防止setState
尝试更新状态:
componentWillUnmount() {
this.isUnmounted = true;
}
这对我来说很脏,所以我已经有一段时间没有使用它了,但是它可以快速解决问题。
答案 1 :(得分:0)
最简单的解决方法(同时也遵循常规的React状态模式)是使用组件的状态有条件地呈现重定向。添加状态为this.state = {isUser: false}
的构造函数,并将{this.state.isUser && <Redirect to="/admin/me" />}
添加到</main>
之前的渲染方法的底部。最后更改
if (props.user) {
return <Redirect to="/admin/me" />
}
到
if (props.user) {
this.setState({isUser: true);
}
其结果遵循常规的React模式,当状态更改为true时,它将自动重定向,而无需执行无操作!