【问题标题】:ReactJS - fetch in async onclick not workingReactJS - 在异步 onclick 中获取不起作用
【发布时间】:2020-05-06 04:10:15
【问题描述】:

当从 onClick 事件处理程序调用时,无法通过异步函数持久化更改。 我有我正在调用的函数:

        retrieveData = async () =>{
        try {
            console.log(1)
            console.log(this.state.ID)
            const url = this.baseUrl + "api/" + this.state.ID
            let response = await fetch(url, {mode: "cors"})
            const data = await response.text()
            this.setState({testVal: data})
            console.log(data)
        } catch (e) {
            console.error(e)
        }
    }

当我将其内容放入 componentDidMount() 并对状态 ID 进行硬编码时,上述函数起作用。但不是当我尝试像这样调用检索到的数据函数时,所以我假设以下 sn-p 是错误所在。

    render() {
        return(
            <div>
                <div>
                    <form>
                        <label>
                            ID:
                            <input type="text" onChange={e => this.setState({ID: e.target.value})}/>
                        </label>
                        <input type="submit" onClick={async () =>{await this.retrieveData();}}/>
                    </form>
                </div>
                <div>
                    {this.state.ID}
                    {this.state.testVal}
                </div>
            </div>
        );
    }

我对 reactJS 还很陌生,所以我相信这很简单。当我点击提交按钮时,我看到控制台吐出1,然后是我刚刚输入的ID,然后两者立即消失。当我检查是否发生了 fecth 时,我没有看到任何对 api 的调用,就像我使用带有 componentDidMount() 的硬编码 url 进行测试时一样,但我希望能够接受用户输入,只是有点不确定如何去做。我相信我已经检查了我能找到的每一个 SO 问题,所以我真的迷路了。如果需要更多信息,请告诉我,谢谢。

【问题讨论】:

  • 我建议为每个异步操作添加一个 try/catch 并检查是否发生任何错误。添加 {mode: "cors"} 将无法解决您正在向其发出请求的服务器的各种 CORS 错误。这也可能在请求级别失败,在.text(),如果它不是文本,而是 application/json
  • @AlexanderStaroselsky 我继续添加了 try catch,我没有收到任何错误,从我的角度来看,似乎 fetch 甚至从未尝试过。
  • 您在开发者工具的网络选项卡中没有看到任何请求?
  • @AlexanderStaroselsky 我重新检查过,我需要尝试拍照,因为它发生得太快了。它确实发出了请求,但只是一瞬间,它出现在我的网络选项卡上,然后立即消失。
  • 我会在几个我知道问题是什么的情况下提交答案。

标签: reactjs async-await onclick


【解决方案1】:

感谢大家的帮助,这是我所做的以下更改。

我变了

<input type="submit" onClick={async () =>{await this.retrieveData();}}/>

到这里

<input type="button" value= "submit" onClick={e=>this.retrieveData(e)}/>

现在它运行良好,所以没有问题。再次感谢。

【讨论】:

    【解决方案2】:

    请查看此示例,您在单击按钮后使用 fetch 调用 api。

    import React, {Component} from "react";
    
    class FetchExample extends React.Component {
        state = {
            isLoading: false,
            questions: [],
            error: null
        };
    
        fetchQuestions = () => {
            fetch(`https://opentdb.com/api.php?amount=10&difficulty=hard&type=boolean`,)
                .then(response => {
                        if (response.status !== 200) {
                            console.log('There was a problem. Status Code: ' + response.status);
                            return;
                        }
                        response.json().then(data => {
                            console.log(data);
                            this.setState({
                                questions: data,
                                isLoading: false
                            })
                        });
                    }
                )
                .catch(function (error) {
                    console.log('Error: ', error);
                    this.setState({error, isLoading: false})
                });
        };
    
        render() {
            const {isLoading, questions, error} = this.state;
            return (
                <React.Fragment>
                    <h1>Random Question</h1>
                    <button onClick={this.fetchQuestions}>Click for calling API using fetch</button>
                    {error ? <p>{error.message}</p> : null}
    
                    {!isLoading && questions.results ? (
                        questions.results.map((questions, index) => {    //something right here
                            //is erroring
                            const {question, category, type, difficulty} = questions;
                            return (
                                <div key={index}>
                                    <p>Question: {question}</p>
                                    <p>Question Type: {type}</p>
                                    <p>Difficulty: {difficulty}</p>
                                    <hr/>
                                </div>
                            );
                        })
                    ) : isLoading ? (
                        <h3>Loading...</h3>
                    ) : null}
                </React.Fragment>
            );
        }
    }
    
    export default FetchExample;
    

    【讨论】:

      【解决方案3】:

      问题是表单提交处理程序正在执行并且正在刷新页面,因为没有阻止默认捕获该提交事件。为了解决这个问题,我建议将处理程序从输入按钮移动到表单处理程序。您还需要防止表单提交发生,您可以通过表单处理程序事件和preventDefault() 来实现。否则提交表单时页面会刷新。

      handleChange = (e) => {
        this.setState({ ID: e.target.value });
      }
      
      retrieveData = async (e) =>{
        e.preventDefault();
      
        try {
            console.log(1)
            console.log(this.state.ID)
            const url = this.baseUrl + "api/" + this.state.ID
            let response = await fetch(url, {mode: "cors"})
            const data = await response.text()
            this.setState({testVal: data})
            console.log(data)
          } catch (e) {
            console.error(e)
          }
      }
      
      render() {
        return(
            <div>
                <div>
                    <form onSubmit={this.retrieveData}>
                        <label>
                            ID:
                            <input type="text" handleChange={this.handleChange} />
                        </label>
                        <button type="submit">Submit</button>
                    </form>
                </div>
                <div>
                    {this.state.ID}
                    {this.state.testVal}
                </div>
            </div>
        );
      }
      

      请注意,我从输入提交控件中删除了单击处理程序,因为我想有两个事件发生在单击按钮然后在表单上提交。当输入提交控件点击发生时,表单本身的提交并没有被阻止并导致页面刷新并阻止 HTTP 请求完成。

      希望对您有所帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-22
        • 2020-07-22
        • 2020-04-12
        • 2021-08-17
        • 2019-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多