我有一个表单输入,允许用户输入文本并提交。 一旦点击了提交按钮,我将通过检查输入是否为空或超过120个字符来验证输入。 我还将输入传递给API,该API检查语法并自动对其进行修复。
现在,我已经收到了来自Axios的答复(可以console.log它),但是在我的数据库和其他地方,它是未更正的版本。
import React, { Component } from "react";
import axios from "axios";
class CreateText extends Component {
constructor() {
super();
this.state = {
textInput: "",
};
}
checkGrammar = async () => {
let response = await axios({
method: 'get',
url: 'https:/an-api-endpoint/',
params: {
apiKey: '',
userId: '',
content: this.state.textInput,
format: 'json'
}
});
const { data } = await response;
// if I console log after this, I see it in my state as the correct version
this.setState({
textInput: data['corrected-content'] ? data['corrected-content'] : this.state.textInput
});
}
handleInput = event => {
this.setState({
textInput: event.target.value
});
}
handleSubmit = event => {
event.preventDefault();
this.validateInput();
if (this.state.textInput) {
// push to db and clear the text state
this.setState({
textInput: ""
});
}
else {
console.log('Failed handle submit');
}
}
validateInput = () => {
if (this.state.textInput !== "") {
if (this.state.textInput.length < 120) {
this.checkGrammar();
}
else {
console.log('Failed validate input');
return; // TODO: Error handling.
}
}
}
render() {
return (
<div className="input">
<form onSubmit={this.handleSubmit}>
<label htmlFor="textInput"></label>
<input
id="textInput"
type="text"
value={this.state.textInput}
onChange={this.handleInput}
placeholder="insert text"
/>
<button className="textButton" type="submit">Submit Text</button>
</form>
</div>
)
}
}
export default CreateText;
我尝试使用async / await setState
到textInput进行响应,我尝试了其他方法,但是当我点击Submit / handleSubmit
时,它调用了API,但是继续并提交,然后获取更正的输入。之后,我可以在文本输入中看到它,这应该不会发生,因为在提交后,状态文本已清除。它使我相信它会被添加,清除,然后axios数据会返回并填充状态(为时已晚)。
我在这里做错了什么吗?我对axios承诺感到困惑,并认为我可以使用setState和async / await来处理它。
谢谢。
答案 0 :(得分:2)
您可以像这样在checkGrammar函数中移动textInput条件逻辑,以避免异步竞争条件:
import React, { Component } from "react";
import axios from "axios";
class CreateText extends Component {
constructor() {
super();
this.state = {
textInput: "",
};
}
checkGrammar = async () => {
let response = await axios({
method: 'get',
url: 'https:/an-api-endpoint/',
params: {
apiKey: '',
userId: '',
content: this.state.textInput,
format: 'json'
}
});
const { data } = response;
// if I console log after this, I see it in my state as the correct version
const textInput = data['corrected-content'] ? data['corrected-content'] : this.state.textInput;
if ( textInput ) {
// push to db and clear the text state
this.setState({
textInput: ""
});
}
else {
console.log('Failed handle submit');
}
}
handleInput = event => {
this.setState({
textInput: event.target.value
});
}
handleSubmit = event => {
event.preventDefault();
this.validateInput();
}
validateInput = () => {
if (this.state.textInput !== "") {
if (this.state.textInput.length < 120) {
this.checkGrammar();
}
else {
console.log('Failed validate input');
return; // TODO: Error handling.
}
}
}
render() {
return (
<div className="input">
<form onSubmit={this.handleSubmit}>
<label htmlFor="textInput"></label>
<input
id="textInput"
type="text"
value={this.state.textInput}
onChange={this.handleInput}
placeholder="insert text"
/>
<button className="textButton" type="submit">Submit Text</button>
</form>
</div>
)
}
}
export default CreateText;
建议:您肯定应该阅读有关异步功能(例如setState
)如何工作的更多信息,并尝试了解异步/等待,因为这类问题每天都会出现。 JavaScript / React中的基础。
如果您打算使用React,则必须了解异步setState
方法的内部工作原理,并了解此方法的回调版本。 StackOverflow post是一个很好的起点。
在帖子中,这可能是最关键的一点:“ setState
以异步的方式工作。这意味着在调用setState
{{1 }}变量不会立即更改。因此,如果您要在状态变量上设置状态后立即执行操作,然后返回结果,则回调将很有用“