简单的React应用程序中的受控组件(复选框)和RESTful模拟存在问题吗?

时间:2019-04-03 21:24:46

标签: reactjs

我正在使用jsonplaceholder来模拟我的数据请求,但是我通过复选框遇到了受控组件的一些问题。困扰我的两种方法是uncompleteTask()/ completeTask(),因为当我尝试单击复选框时,它会完全抹掉整个帖子列表。

我的目标是能够根据完整/ id /标题进行排序,并选中/取消选中每个任务。任何帮助将不胜感激。...

import React, { Component } from "react";

const restfulAPI = "https://jsonplaceholder.typicode.com/todos";

class App extends Component {
  constructor(props) {
    super(props)
    this.state = { filter: "id", tasks: []};
  }

  componentDidMount() {
    fetch(`${restfulAPI}`)
      .then(response => response.json())
      .then(tasks => this.setState({ tasks }));
  }

  uncompleteTask = id => {
    fetch(`${restfulAPI}/${id}`, {
      method: "PATCH",
      body: JSON.stringify({
        completed: false
      }),
      headers: {
        "Content-type": "application/json; charset=UTF-8"
      }
    })
      .then(response => response.json())
      .then(json => {
        let newTasks = [];
        for (let i = 0; i < this.state.tasks.length; i++) {
          newTasks = newTasks.concat(
            json.id === this.state.tasks[i].id
              ? { ...this.state.tasks[i], completed: false }
              : this.state.tasks[i]
          );
        }
        this.setState({
          tasks: newTasks
        });
      });
  };

  completeTask = id => {
    fetch(`${restfulAPI}/${id}`, {
      method: "PATCH",
      body: JSON.stringify({
        completed: true
      }),
      headers: {
        "Content-type": "application/json; charset=UTF-8"
      }
    })
      .then(response => response.json())
      .then(json => {
        let newTasks = [];
        for (let i = 0; i < this.state.tasks.length; i++) {
          newTasks = newTasks.concat(
            json.id === this.state.tasks[i].id
              ? { ...this.state.tasks[i], completed: true }
              : this.state.tasks[i]
          );
        }
        this.setState({
          tasks: newTasks
        });
      });
  };

  getSortedTasks = () => {
    return this.state.tasks.sort((a, b) => {
      if (this.state.filter === "id") {
        return a.id > b.id ? 1 : -1;
      }

      if (this.state.filter === "completed") {
        return a.completed ? -1 : 1;
      }

      if (this.state.filter === "title") return a.title > b.title ? 1: -1;
    });
  };

  setFilterCompleted = () => {
    this.setState({ filter: "completed" });
  }

  setFilterId = () => {
    this.setState({ filter: "id" });
  }

  setFilterTitle = () => {
    this.setState({ filter: "title" });
  }

  addTask = () => {
    const task = document.getElementById("newTask").value;
    fetch("https://jsonplaceholder.typicode.com/todos", {
      method: "POST",
      body: JSON.stringify({
        title: task,
        userId: 1,
        completed: false
      }),
      headers: {
        "Content-type": "application/json; charset=UTF-8"
      }
    })
      .then(response => response.json())
      .then(json => this.setState({ tasks: this.state.tasks.concat({ ...json, id: this.state.tasks.length + 1 }) }));
  };


  render() {
    const tasks = this.getSortedTasks();

    return (
      <div className="main">
        <div>
          Add Task: <input id="newTask" />
          <button onClick={this.addTask}>Add</button>
        </div>
        <table>
          <thead>
            <tr>
              <th onClick={this.setFilterCompleted}>✓</th>
              <th onClick={this.setFilterId}>ID</th>
              <th onClick={this.setFilterTitle}>Task</th>
            </tr>
          </thead>
          <tbody>
            {tasks.map(task => (
              <tr key={task.id}>
                <td>
                  {task.completed ? (
                    <input
                      onChange={this.uncompleteTask}
                      checked
                      type="checkbox"
                    />
                  ) : (
                    <input type="checkbox" onChange={this.completeTask} />
                  )}
                </td>
                <td>{task.id}</td>
                <td className="strikethrough">{task.title}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }
}

export default App;

1 个答案:

答案 0 :(得分:1)

因为concat不修改newTasks,它返回的结果将是两个数组的串联。

您的newTasks始终是一个空数组

尝试一下:

        let newTasks = [];
        for (let i = 0; i < this.state.tasks.length; i++) {
          newTasks = newTasks.concat(
            json.id === this.state.tasks[i].id
              ? { ...this.state.tasks[i], completed: false }
              : this.state.tasks[i]
          );
        }
        this.setState({
          tasks: newTasks
        });

只是为了使其更清晰

let a = [1];
let b = [2,3];
let result = a.concat(b);
// a = [1]; b = [2,3]; result = [1,2,3]; 

详细了解此here