React组件未呈现Axios请求的响应

时间:2019-11-29 23:06:06

标签: javascript reactjs async-await axios

我有一个表单输入,允许用户输入文本并提交。 一旦点击了提交按钮,我将通过检查输入是否为空或超过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来处理它。

谢谢。

1 个答案:

答案 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;

Codesandbox

建议:您肯定应该阅读有关异步功能(例如setState)如何工作的更多信息,并尝试了解异步/等待,因为这类问题每天都会出现。 JavaScript / React中的基础。

如果您打算使用React,则必须了解异步setState方法的内部工作原理,并了解此方法的回调版本。 StackOverflow post是一个很好的起点。

在帖子中,这可能是最关键的一点:“ setState异步的方式工作。这意味着在调用setState {{1 }}变量不会立即更改。因此,如果您要在状态变量上设置状态后立即执行操作,然后返回结果,则回调将很有用