React componentDidMount 和 setState 似乎不会导致重新渲染以显示我的组件

React componentDidMount and setState not seeming to cause a rerender to show my component

/*获取数据并设置状态后,我正在尝试生成一个 jsx 项目数组来显示。但是数组显示为空,没有任何渲染。

尝试过,硬编码并且有效。尝试登录数据,它确实显示状态正在接收数据。

从下面的代码中删除了我的授权令牌。 */

import React, { Component } from 'react';
import AddCard from '../AddCard/AddCard.js';
import KanCard from '../KanCard/KanCard.js';
import './CardHolder.scss';

export default class CardHolder extends Component {
  constructor(props){
    super(props);
    this.state = {
      stories: [],
      inProgressTasks: [],
      completeTasks: [],
    };
  }

  componentDidMount(){
    // let id = this.props.id;
    let id = 168881069;
    let completetask = [];
    let progresstask =[];
    var data = null;
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = false;

    xhr.addEventListener("readystatechange", function () {
      if (this.readyState === 4) {
        let parsedResponse = JSON.parse(this.responseText);
        for( let taskResponse of parsedResponse ){
          let task = {
              key:taskResponse.id,
              id:taskResponse.id,
              story_id:taskResponse.story_id,
              complete:taskResponse.complete,
              description: taskResponse.description,
        }
          if(!taskResponse.complete){
            progresstask.push(task)
          } else {
            completetask.push(task);
          }
        }
      }
    });
    this.setState({inProgressTasks:progresstask, completeTasks:completetask})
    xhr.open("GET", `https://www.pivotaltracker.com/services/v5/projects/2401708/stories/${id}/tasks`);
    xhr.setRequestHeader("X-TrackerToken", "296912a3ff4ddcda26b4a419934b3051");
    xhr.setRequestHeader("Accept", "*/*");
    xhr.setRequestHeader("Cache-Control", "no-cache");
    xhr.setRequestHeader("cache-control", "no-cache");
    xhr.send(data);
  }

    render(){

      let completeTasks = this.state.completeTasks.map((task)=>{
        return (
          <KanCard
          key = {task.id}
          id = {task.id}
          story_id = {task.story_id}
          complete = {task.complete}
          description = {task.description}
          />
        )
      })
      let inProgressTasks = this.state.inProgressTasks.map((task)=>{
        return (
          <KanCard
            key = {task.id}
            id = {task.id}
            story_id = {task.story_id}
            complete = {task.complete}
            description = {task.description}
            />
        )
      })
      console.log(inProgressTasks)
      return (
          <div className='holder'>
            <h2> {this.props.title} </h2>
            <div>
              <h3>In Progress</h3>
              {inProgressTasks}
            </div>
            <div>
              <h3>Complete</h3>
              {completeTasks}
            </div>

            <AddCard />
          </div>
      )
    }  
}

您设置呼叫和更新状态的方式存在一些问题。

首先,确保在收到响应时更新状态,毕竟这是一个异步请求,您需要等待获取某些内容,然后更新状态。

xhr.addEventListener("readystatechange", function () {
      if (this.readyState === 4) {
        let parsedResponse = JSON.parse(this.responseText);
        for( let taskResponse of parsedResponse ){
          let task = {
              key:taskResponse.id,
              id:taskResponse.id,
              story_id:taskResponse.story_id,
              complete:taskResponse.complete,
              description: taskResponse.description,
        }
          if(!taskResponse.complete){
            progresstask.push(task)
          } else {
            completetask.push(task);
          }
        }

        this.setState({inProgressTasks:progresstask, completeTasks:completetask})
      }
    });

其次,请记住您在 class 中,因此当您使用关键字 this 时,this.readyStatethis.responseText 引用 class,不是您期望的 XHR 对象。为了完成这项工作,您应该将 readystatechange 的回调函数更改为 lambda 函数,然后将 this 替换为 xhr,但您应该保留 this实际上在 this.setState:

中引用了你的 class
xhr.addEventListener("readystatechange", () => {
          if (xhr.readyState === 4) {
            let parsedResponse = JSON.parse(xhr.responseText);
            for( let taskResponse of parsedResponse ){
              let task = {
                  key:taskResponse.id,
                  id:taskResponse.id,
                  story_id:taskResponse.story_id,
                  complete:taskResponse.complete,
                  description: taskResponse.description,
            }
              if(!taskResponse.complete){
                progresstask.push(task)
              } else {
                completetask.push(task);
              }
            }

            this.setState({inProgressTasks:progresstask, completeTasks:completetask})
          }
        });

我试图在此处复制您的问题:

我正在打一个哑巴 api 并使用响应数据更新我的状态。玩弄它。将 readystatechange 的回调函数从 lambda 函数更改为您最初设置的匿名函数,看看会发生什么。

要了解有关 this 问题的更多信息,请查看 this question