reactjs - React:调用父挂钩导致子无法安全渲染
问题描述
我正在尝试在 React 中实现基于 JWT 的身份验证。我从 digitalocean 学习了本教程,但使用了 axios(基于 promise)而不是 fetch API。
如果身份验证失败,则按要求显示错误消息,并且在成功登录时,将显示正确的页面。然而,React 会抛出以下错误:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
我想这是因为我调用 loginpage 父级的钩子来.then()
从 axios 承诺的调用中设置 JWT,但是一旦设置了 jwt,父级将停止呈现 loginpage 并且它是 axios 承诺。我将如何巧妙地解决这个问题?
function App() {
const [token, setToken] = useState();
if(!token) {
return <EmployeeLogin setToken={setToken} />;
}
return (
<main>
<Switch>
<Route path="/someroute" component={someComponent} exact />
</Switch>
</main>
);
}
export default App;
// EmployeeLogin.jsx
const styles = theme => ({ ... });
class EmployeeLogin extends React.Component {
constructor(props) {
super(props);
const { setToken } = this.props;
this.state = {
email: '',
password: '',
error: null,
isLoading: false,
};
this.handleSubmitevents = this.handleSubmitevents.bind(this);
}
async handleSubmitevents(event) {
event.preventDefault();
const credentials = {
email: this.state.email,
password: this.state.password,
}
this.setState({
isLoading: true,
error: null,
});
axios.post('http://localhost:8080/account/employee/login', credentials, {
headers: {
"Content-Type": 'application/json', 'Accept': 'application/json'
}
})
.then(res => {
this.props.setToken(res.data.token); // Set the token to the parent (App.js)
})
.catch(error => {
this.setState({
error: error.response.data.message, // Show error message on failure
});
})
.then(() => {
this.setState({ isLoading: false }); // Always stop the loading indicator when done
});
}
componentWillUnmount() {
// How to terminate the promise neatly here?
}
render() {
const { classes } = this.props;
return (
<form className={classes.form} onSubmit={this.handleSubmitevents} noValidate>
<TextField
required
value={this.state.email}
onChange={(e) => { this.setState({ email: e.target.value }); }}
/>
<TextField
required
type="password"
value={this.state.password}
onChange={(e) => { this.setState({ password: e.target.value }); }}
/>
<Button type="submit">Sign In</Button>
</form>
);
}
}
EmployeeLogin.propTypes = {
classes: PropTypes.object.isRequired,
setToken: PropTypes.func.isRequired,
};
export default withStyles(styles)(EmployeeLogin);
解决方案
setToken
设置为 false 后尝试调用,isLoading
以便您可以尝试以下操作。
async handleSubmitevents(event) {
event.preventDefault();
const credentials = {
email: this.state.email,
password: this.state.password,
}
this.setState({
isLoading: true,
error: null,
});
let responseToken = ''; // set responseToken to blank before calling api
axios.post('http://localhost:8080/account/employee/login', credentials, {
headers: {
"Content-Type": 'application/json', 'Accept': 'application/json'
}
})
.then(res => {
responseToken = res.data.token; // set responseToken here
})
.catch(error => {
this.setState({
error: error.response.data.message, // Show error message on failure
});
})
.then(() => {
this.setState({ isLoading: false });
this.props.setToken(responseToken); // call props method from here
});
}
推荐阅读
- python - 当 Pandas DataFrame 中的某个值在另一列中实现时,如何编辑一列中的值?
- python - View 没有返回 HttpResponse 对象。它返回 None 代替。当与 FormView 一起使用正常形式时,django
- java - 属性名称中的 JBoss CLI 特殊字符
- python - 将数据发送到烧瓶而不重新加载页面
- c++ - c++ 项目中令人困惑的定义指令
- java - 休眠搜索将一个实体索引到两个不同的索引
- selenium - Selenium 未通过代理加载页面,显示构建信息:版本:'未知',修订:'未知',时间:'未知'
- c++ - 结构化绑定初始化程序表单 { assignment-expression } 在 clang 上的数组类型失败
- python - 如果 Pandas 数据框中的两个布尔值为真,如何替换元素
- webpack - 运行 webpack encore 时出现语法错误