【问题标题】:How to remove data from API with HTTP Request [React TS]如何使用 HTTP 请求从 API 中删除数据 [React TS]
【发布时间】:2020-01-29 13:50:26
【问题描述】:

所以我一直在为一个页面创建一个管理控制面板,该面板显示一个卡片列表,一旦点击,就会将用户重定向到视频或基于文本的链接。我还必须添加一个 CRUD 功能,允许我从提供的 API 中编辑/删除帖子。

API 是本地托管的,因此请求“localhost:3000/videos/{Id}”将加载具有以下字段的对象:“id”、“url”、“title”和“thumbnail”

我有一个类是用来制作卡片的,叫HelpCard.tsx 代码如下:

import React, { Component } from "react";
import "../help/HelpCard.css";
import "../help/HelpList";
import spinner from "../help/spinner.gif";
import { string, number } from "prop-types";
import { Link } from "react-router-dom";

interface Props {
  url: string;
  title: string;
  thumbnail: string;
}

interface State {
  title: string;
  thumbnail: string;
  id: string;
  imageLoading?: boolean;
  tooManyRequests?: boolean;
}

export default class HelpCard extends Component<Props, State> {
  state = {
    id: "",
    title: "",
    imageLoading: true,
    tooManyRequests: false,
    thumbnail: "",
    deleteProduct: true
  };

  componentDidMount() {
    const { url, title, thumbnail } = this.props;
    const id = url.split("/")[url.split("/").length - 2];

    this.setState({
      id,
      title,
      thumbnail,
      imageLoading: true,
      tooManyRequests: false
    });
  }

  render() {
    const isThumbnail = this.state.thumbnail;
    const adminhelpcard = this.state;
    return (
      <div>
        {isThumbnail ? (
          <div className="horizontalCard">
            <div className="innerCard">
              <div className="leftImage">
                <img
                  className="Sprite"
                  onLoad={() => this.setState({ imageLoading: false })}
                  onError={() => this.setState({ tooManyRequests: true })}
                  src={this.state.thumbnail}
                  style={
                    this.state.tooManyRequests
                      ? { display: "none" }
                      : this.state.imageLoading
                      ? { display: "null" }
                      : { display: "null" }
                  }
                />
              </div>
              <div className="rightText">
                <div className="card-body">
                  {this.state.title}
                  <div className="cardButtons">
                    <button className="btn btn-update btn-outline-primary">Update</button>
                    <button
                      onClick={() => adminhelpcard.deleteProduct(this.state.id)}
                      className="btn btn-outline-primary">
                      Delete
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>

然后我有负责以列表形式显示卡片的 HelpList.tsx 模块。代码如下:

import React, { Component } from "react";
import HelpCard from "./HelpCard";
import "../help/HelpCard.css";
import axios from "axios";
import InfiniteScroll from "react-infinite-scroller";
import { Button } from "components/ui";

interface State {
  url: string;
  adminhelpcard: SingleAdminHelpCard[];
  error: null;
  response: {};
}

interface SingleAdminHelpCard {
  id: string;
  url: string;
  title: string;
  thumbnail: string;
}

interface Props {}

export default class HelpList extends Component<Props, State> {
  state = {
    id: "",
    url: "http://localhost:3000/videos/",
    adminhelpcard: [],
    itemsCountPerPage: 1,
    activePage: 1,
    error: null,
    response: {}
  };

  loadAdminHelpCard = () => {
    axios
      .get(this.state.url)
      .then((res) => {
        this.setState((prevState) => {
          const adminhelpcard = prevState.adminhelpcard;
          return {
            adminhelpcard: [...prevState.adminhelpcard, ...res.data],
            url: res.data.next
          };
        });
      })
      .catch(function(error) {
        // handle error
        console.log(error);
      });
  };

  async componentDidMount() {
    const apiUrl = "http://localhost:3000/videos/";
    const res = await axios.get(this.state.url);
    this.setState({ adminhelpcard: res.data });
    fetch(apiUrl)
      .then((res) => res.json())
      .then(
        (result) => {
          this.setState({
            adminhelpcard: result
          });
        },
        (error) => {
          this.setState({ error });
        }
      );
  }

  deleteProduct(id: any) {
    const { adminhelpcard } = this.state;

    const apiUrl = `http://localhost:3000/videos/${this.state.id}`;

    const options = {
      method: "DELETE"
    };

    fetch(apiUrl, options)
      .then((res) => res.json())
      .then(
        (result) => {
          this.setState({
            response: result,
            adminhelpcard: adminhelpcard.filter((adminhelpcard: SingleAdminHelpCard) => adminhelpcard.id !== id)
          });
        },
        (error) => {
          this.setState({ error });
        }
      );
  }

  render() {
    console.log(this.state.adminhelpcard);
    return (
      <div>
        <React.Fragment>
          {this.state.adminhelpcard ? (
            <div className="row">
              <InfiniteScroll
                pageStart={1}
                loadMore={this.loadAdminHelpCard}
                hasMore={this.state.url ? true : false}
                threshold={0}
                loader={
                  <div className="loader" key={0}>
                    Loading ...
                  </div>
                }>
                {this.state.adminhelpcard.map((adminhelpcard: SingleAdminHelpCard, i) => (
                  <HelpCard
                    key={adminhelpcard.id + i}
                    title={adminhelpcard.title}
                    url={adminhelpcard.url}
                    thumbnail={adminhelpcard.thumbnail}
                  />
                ))}
              </InfiniteScroll>
            </div>
          ) : (
            <h1>Loading Cards</h1>
          )}
        </React.Fragment>
      </div>
    );
  }
}

我收到以下错误:

This expression is not callable.
  Type 'Boolean' has no call signatures.ts(2349)

来自代码行中的“deleteProduct”函数:

onClick={() => adminhelpcard.deleteProduct(this.state.id)}

当我尝试单击帮助卡上的删除按钮时,它说没有识别出名为“deleteProduct”的函数。我该如何解决这个问题?

--------------编辑-------- --------

将 deleteProduct 添加到 HelpCard 组件时出现错误。

"没有重载匹配这个调用。 重载 1 of 2,“(道具:只读):HelpCard”,给出了以下错误。 键入'{键:字符串;标题:字符串;网址:字符串;缩略图:字符串; deleteProduct: (id: any) => void; }' 不可分配给类型 'IntrinsicAttributes & IntrinsicClassAttributes & Readonly & Readonly'。 类型“IntrinsicAttributes & IntrinsicClassAttributes & Readonly & Readonly'。”

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    首先,您需要将deleteProduct 函数作为prop 传递给HelpCard 组件。

    因此,在您的 HelpList.tsx 中,向 &lt;HelpCard/&gt; 元素添加另一个道具,如下所示。

    <HelpCard
        key={adminhelpcard.id + i}
        title={adminhelpcard.title}
        url={adminhelpcard.url}
        thumbnail={adminhelpcard.thumbnail}
        deleteProduct={this.deleteProduct.bind(this)}
    />
    

    然后你需要在HelpCard 组件中的onClick 处理程序中使用它。

    <button
        onClick={() => this.props.deleteProduct(this.state.id)}
        className="btn btn-outline-primary">
            Delete
    </button>
    

    您可能需要更改HelpCard 中的Props 接口以适应这个新道具。

    interface Props {
      url: string;
      title: string;
      thumbnail: string;
      deleteProduct: (id: any) => void;
    }
    

    【讨论】:

    • 在哪里/如何将最上面的代码块放在 HelpCard.tsx 中?或者我将如何通过 deleteproduct
    • 它进入你的HelpList.tsx
    • 更新了我的答案。在您的HelpList.tsx 的渲染方法中,您已经有一个HelpCard 元素。如图所示,只需为其添加另一个道具。
    • 将“deleteProduct={this.deleteProduct}”添加到 给出了添加到我原始问题中的错误。
    • 您可能还需要修改您的Props 接口。更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2020-05-31
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2021-09-22
    • 1970-01-01
    相关资源
    最近更新 更多