简体   繁体   English

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

[英]React component not rendering response of Axios request

I have a form input that allows a user to input text and submit it.我有一个表单输入,允许用户输入文本并提交。 Once the submit button is hit, I validate the input by checking if it's empty or longer than 120 characters.点击提交按钮后,我会通过检查输入是否为空或超过 120 个字符来验证输入。 I also pass the input to an API that checks the grammar and will fix it automatically.我还将输入传递给检查语法并自动修复它的 API。

Right now, my response from Axios is there (I can console.log it), but in my database and other places it is the uncorrected versions.现在,我的 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;

I try to setState to textInput for the response using async/await, I tried other methods, but it seems when I hit the Submit/ handleSubmit , it calls out to the API, but continues and submits, then gets the corrected input.我尝试setState来为textInput为响应异步使用/ AWAIT,我尝试过其他方法,但似乎当我点击提交/ handleSubmit ,它调用该API,而是继续并提交,然后得到校正输入。 I can see it on my text input afterwards which shouldn't happen since after submitting, the state text is cleared.之后我可以在我的文本输入中看到它,这不应该发生,因为提交后,状态文本被清除。 It leads me to believe that it gets added, cleared, then axios data comes back and fills in the state (too late.)它让我相信它被添加、清除,然后 axios 数据返回并填充状态(为时已晚。)

Am I doing something blatantly wrong here?我在这里做错了什么吗? I'm confused about the axios promise and thought I could handle it with setState and async/await.我对 axios 承诺感到困惑,并认为我可以使用 setState 和 async/await 来处理它。

Thanks.谢谢。

You can move the textInput conditional logic in the checkGrammar function like this to avoid asynchronous race conditions:您可以像这样移动 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代码沙盒

Suggestion: You should definitely read more about how async functions (like setState ) work, and try to understand async/await, since these kind of issues will come forth on a daily basis in JavaScript/React.建议:您绝对应该阅读更多关于异步函数(如setState )如何工作的内容,并尝试了解 async/await,因为 JavaScript/React 中每天都会出现此类问题。

If you intend to work with React, you must understand the inner workings of the asynchronous setState method, and learn about the callback version of this method.如果您打算使用 React,您必须了解异步setState方法的内部工作原理,并了解该方法的回调版本。 A good starting point is this StackOverflow post .这个StackOverflow 帖子是一个很好的起点。

From the post, this is probably the most crucial point: " setState works in an asynchronous way. That means after calling setState the this.state variable is not immediately changed. so if you want to perform an action immediately after setting state on a state variable and then return a result, a callback will be useful "从帖子中,这可能是最关键的一点:“ setState异步方式工作。这意味着在调用setStatethis.state变量不会立即更改。因此,如果您想在对状态设置状态后立即执行操作变量然后返回一个结果,回调将是有用的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM