【问题标题】:How to render an updated state in my div element?如何在我的 div 元素中呈现更新的状态?
【发布时间】:2019-08-10 15:24:57
【问题描述】:

我有一个按钮设置为:

  1. 对 GET 数据进行 API 调用,并从 数据;
  2. 返回这些标题;
  3. 用这些标题更新我的组件的“文本”状态
  4. 在 div 中显示这些标题

似乎所有这些事情都在发生;但也许不是为了?我可以看出 this.state.text 按预期更新了标题,但是 DOM 没有收到更新的状态。我以可以在样板 React 应用程序的“index.js”文件中运行的格式附加了代码。

我尝试过弄乱操作顺序,将 getAllPosts() 函数输出为数组,以及无数的数组操作。

import React from 'react';
import ReactDOM from 'react-dom';



class AllPosts extends React.Component {
    constructor(props) {
      super(props);
      this.state = {text: 'poop'};
    }

    getAllPosts(){
      var request = new XMLHttpRequest();
      var titles=[];
      request.open('GET', 'http://jsonplaceholder.typicode.com/posts', true)
      request.onload = function () {
        var data = JSON.parse(this.response);   
        if (request.status >= 200 && request.status < 400) {
          data.forEach(post => {
            titles.push(post.title);
          })
        } else {
          console.log('error getting title list.  Please try again.');
        }
      }
      request.send();
      console.log(titles);
      return titles;
    }  

    onClickButton = () => {
      var allTitles = this.getAllPosts();
      this.setState({text: allTitles});
      console.log(this.state.text);
      console.log(this.allTitles);  
    }  

    render() {
      return (
        <div>
        <button
          onClick={this.onClickButton}>
            Get All Posts
        </button>
        <div>{this.state.text}</div>
        </div>
      );
    }
  }

  function App() {
    return (      
      <div className="App">
        <header className="App-header">

          <AllPosts />
        </header>
      </div>
    );
  }

  export default App;

ReactDOM.render(<App />, document.getElementById('root'));

(打开控制台) 预期结果是 div 文本在点击时发生变化,从“便便”变为标题列表。发生的事情是数据“未定义”并且文本被空白。再次单击该按钮时,当我要求它记录 this.state.text 时,标题列表将填充到控制台中,因此它显然已进入状态。但是状态不会在页面上更新。

【问题讨论】:

标签: javascript reactjs react-native jsx


【解决方案1】:

您需要将您的 XMLHttpRequest 包装在一个承诺中:

getAllPosts = () => {
  new Promise((resolve, reject) => {
    var request = new XMLHttpRequest();
    var titles = [];
    request.open('GET', 'http://jsonplaceholder.typicode.com/posts', true)
    request.onload = function () {
      var data = JSON.parse(this.response);
      if (request.status >= 200 && request.status < 400) {
        data.forEach(post => {
          titles.push(post.title);
        })
        resolve(titles);
      } else {
        reject('error getting title list.  Please try again.');
      }
    }
    request.send()
  }).then(titles => {
    this.setState({ allTitles: titles })
  }).catch((error) => {
    console.log(error)
  })
}

您的 onClickButton() 现在应该只调用 getAllPosts() 而不是其他任何东西。

onClickButton = () => {
  this.getAllPosts()
}

【讨论】:

  • 我尝试了您的代码示例,但 API 调用现在没有发生。 XHR 请求没有被发送,看起来像?
  • @n00bEternal 抱歉,我忘了加request.send()。我已经更新了我的代码以包含它。
  • 不,我应该道歉。我将您的解决方案与我当前的产品进行了比较,应该已经看到了。我是一个 n00b,但不是一个 :) 谢谢!
  • @n00bEternal 嘿,别担心!在某种程度上,我们都是菜鸟:)
【解决方案2】:

使用 Axios 进行 API 调用,它将使您的代码更简单、更易于使用,并且更具视觉吸引力。

如果您对代码有任何疑问,请发表评论。 这是Axios 的文档。

import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';



class AllPosts extends React.Component {
    constructor(props) {
      super(props);
      this.state = {text: 'foo'};
    }

    async getAllPosts () {
      var titles = [];

      const response = await axios.get('http://jsonplaceholder.typicode.com/posts')
      const data = response.data;

      data.forEach((post) => {
          titles.push(post.title);
      })

      return titles;
    }  

    onClickButton = async () => {
      var allTitles = await this.getAllPosts();

      this.setState({ text: allTitles });
    }  

    render() {
      return (
        <div>
        <button
          onClick={this.onClickButton}>
            Get All Posts
        </button>
        <div>{this.state.text}</div>
        </div>
      );
    }
  }

  function App() {
    return (      
      <div className="App">
        <header className="App-header">

          <AllPosts />
        </header>
      </div>
    );
  }

  export default App;

  ReactDOM.render(<App />, document.getElementById('root'));

【讨论】:

    【解决方案3】:

    您可以将您的请求包装在Promise 中,并从getAllPosts 函数返回promise

    getAllPosts = () => {
      return new Promise((resolve, reject) => {
        var request = new XMLHttpRequest();
        var titles = [];
        request.open('GET', 'http://jsonplaceholder.typicode.com/posts', true)
        request.onload = function() {
          var data = JSON.parse(this.response);
          if (request.status >= 200 && request.status < 400) {
            data.forEach(post => {
                titles.push(post.title);
            })
            resolve(titles);
          } else {
            console.log("fail")
            reject('error getting title list.  Please try again.');
          }
        }
        request.send();
      })
    }
    

    你的onClickButton 函数应该是,

    onClickButton = () => {
      let allTitles = this.getAllPosts();
      allTitles.then(titles => {
         console.log("success");
         this.setState({ text: titles })
      }).catch((error) => { 
         console.log(error)
      })
    }
    

    另一种简单的方法是使用fetch

    getAllPosts = () => {
      fetch("http://jsonplaceholder.typicode.com/posts")
        .then(response => response.json())
        .then(titles => {
          console.log("success");
          let title = [];
          titles.forEach(post => {
              title.push(post.title);
          })
          this.setState({ text: title })
        }).catch((error) => {
            console.log(error)
        })
    }
    

    你的onClickButton 函数应该是,

    onClickButton = () => {
       this.getAllPosts();
    }  
    

    【讨论】:

      猜你喜欢
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 2023-01-31
      • 2020-03-06
      • 1970-01-01
      • 2022-08-16
      • 1970-01-01
      • 2021-09-09
      相关资源
      最近更新 更多