如何在不刷新页面的情况下更新列表

时间:2019-10-24 14:37:00

标签: javascript reactjs typescript

我有一个API,可为我提供具有以下属性的对象:id,title,url,thumbnailUrl。

我有一个模块负责该卡,该模块具有以下代码:

export interface Manual {
  id?: string | number;
  url: string;
  title: string;
  thumbnail?: string | null;
}

我有一个模块负责创建实际的HelpCard组件,其代码如下:

interface Props {
  card: Manual;
  deleteProduct: Function;
  editProduct: Function;
  type: "videos" | "manuals";
}

interface State {
  editedCard: Manual;
  imageLoading?: boolean;
  tooManyRequests?: boolean;
}

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

  componentDidMount() {}

  onEditClick = (card: Manual): void => {
    this.setState({ editedCard: card });
  };

  updateEditCard = (event: React.FormEvent<HTMLInputElement>, key: "url" | "title" | "thumbnail"): void => {
    const value = event.currentTarget.value;
    this.setState((prevState: State) => {
      return { editedCard: { ...prevState.editedCard, [key]: value } };
    });
  };

  render() {
    const { card } = this.props;
    const { editedCard } = this.state;
    return (
      <React.Fragment>
        <div className="card">
          <div className="card-img">
            {this.state.imageLoading ? <img src={placeholder} style={{ width: "100%", height: "100%" }}></img> : null}
            <img
              className="cardImage"
              style={
                this.state.tooManyRequests
                  ? { display: "none" }
                  : this.state.imageLoading
                  ? { display: "null" }
                  : { display: "block" }
              }
              onLoad={() => this.setState({ imageLoading: false })}
              onError={() => this.setState({ tooManyRequests: true })}
              src={card.thumbnail ? card.thumbnail : placeholder}
            />
          </div>

          <div className="card-body">
            <div style={{ textAlign: "center" }}>
              <span className="card-title">{card.title}</span>
              <hr></hr>
            </div>
            <div className="card-buttons">
              <div className="group">
                <Modal
                  trigger={
                    <Button
                      onClick={() => this.onEditClick(card)}
                      style={{ width: "90px" }}
                      icon="mode_edit"
                      className="btn blue-outline"
                      href="#!">
                      Edit
                    </Button>
                  }>
                  <form
                    onSubmit={(e) => e.preventDefault()}
                    id="videoCardEdit"
                    style={{ width: "auto", height: "auto" }}>
                    <div>
                      <div>
                        <label>Title:</label>
                        <input
                          className="input"
                          style={{ width: "100%" }}
                          name="videoCardTitle"
                          onChange={(e: React.FormEvent<HTMLInputElement>) => this.updateEditCard(e, "title")}
                          value={editedCard.title}></input>
                      </div>
                      <div>
                        <label>URL:</label>
                        <input
                          className="input"
                          style={{ width: "100%" }}
                          name="videoCardURL"
                          onChange={(e: React.FormEvent<HTMLInputElement>) => this.updateEditCard(e, "url")}
                          value={editedCard.url}></input>
                      </div>
                      <div>
                        <label>Thumbnail URL:</label>
                        <input
                          className="input"
                          style={{ width: "100%" }}
                          name="videoCardThumbnail"
                          onChange={(e: React.FormEvent<HTMLInputElement>) => this.updateEditCard(e, "thumbnail")}
                          value={editedCard.thumbnail}></input>
                      </div>
                      <br></br>
                    </div>
                    <Button
                      type="submit"
                      className="btn green-outline"
                      icon="check"
                      length="fullwidth"
                      style={{
                        float: "left"
                      }}
                      onClick={() =>
                        this.props.editProduct(
                          card.id,
                          editedCard.title,
                          editedCard.url,
                          editedCard.thumbnail,
                          this.props.type
                        )
                      }>
                      confirm
                    </Button>
                    <br></br>
                  </form>
                </Modal>
                <Button
                  icon="delete"
                  style={{ width: "90px" }}
                  onClick={() => this.props.deleteProduct(card.id, this.props.type)}
                  className="btn red-outline">
                  Delete
                </Button>
              </div>
            </div>
          </div>
        </div>
      </React.Fragment>
    );
  }
}

然后,使用以下代码将该卡显示在HelpList组件上:

export default class HelpList extends Component<Props, State> {
  state = {};

  async componentDidMount() {}

  render() {
    console.log(this.props.data);

    return (
      <div className="row">
        {this.props.data.map((card: Manual) => (
          <HelpCard
            card={card}
            key={card.id}
            deleteProduct={this.props.onDelete}
            editProduct={this.props.onEdit}
            type={this.props.type}
          />
        ))}
      </div>
    );
  }
}

在HelpAdmin.view.tsx模块上显示的最终列表,该模块加载我的卡,并具有所有API功能,例如我的创建/删除/编辑调用。

状态和加载功能如下:

export class HelpAdminView extends Component<Props, State> {
  state = {
    title: "",
    thumbnail: "",
    url: "",
    error: null,
    isEditProduct: true,
    isAddProduct: true,
    whichRadioSelected: "video",
    videos: [],
    manuals: []
  };
  componentDidMount() {
    this.loadAdminHelpCard("videos");
    this.loadAdminHelpCard("manuals");
  }

  loadAdminHelpCard = (type: "videos" | "manuals"): void => {
    const url = `${BASE_API_URL}/${type}`;
    axios
      .get(url)
      .then((res) => {
        this.setState({ [type]: res.data } as any);
      })
      .catch(function(error) {
        // handle error
        console.log(error);
      });
  };

最后,我的编辑功能如下:

editProduct = (id: any, title: string, url: string, thumbnail: string, type: "videos" | "manuals") => {
    const apiUrl = `${BASE_API_URL}/${type}/${id}`;

    axios
      .put(apiUrl, {
        title: title,
        url: url,
        thumbnail: thumbnail
      })
      .then((response: any) => {
        // ? UPDATE the list with new card information here
      })
      .catch(function(error) {
        console.log(error);
      });
  };

当用户单击“编辑”时,会将卡片从道具中复制并进入一种状态。现在仅编辑卡的状态。 (this.state.editedCard)当用户单击提交时,editedCard的详细信息将提供给editProduct(id,标题,缩略图等)。 在HelpAdmin.view.tsx中,正在进行API调用,该调用将使用新卡的详细信息更改数据库。

我要弄清楚的是如何在视频/手册中更新我们的卡,以使其反映在用户界面中。 (启用成功的API调用)

在此先感谢您的阅读和帮助!

1 个答案:

答案 0 :(得分:1)

当更新操作结束时,您可以获得当前数据。

.then((response: any) => {
    //here get the recent data from your api
    // ? UPDATE the list with new card information here
    this.loadAdminHelpCard("videos");
    this.loadAdminHelpCard("manuals");
  })

因此,这将更新状态,从而导致父组件重新呈现,这也将重新呈现子组件,因此您的Card组件将获取新数据。

所有editProduct函数:

  editProduct = (id: any, title: string, url: string, thumbnail: string, type: "videos" | "manuals") => {
    const apiUrl = `${BASE_API_URL}/${type}/${id}`;

    axios
      .put(apiUrl, {
        title: title,
        url: url,
        thumbnail: thumbnail
      })
      .then((response: any) => {
        //here get the recent data from your api
        // ? UPDATE the list with new card information here
        this.loadAdminHelpCard("videos");
        this.loadAdminHelpCard("manuals");
      })
      .catch(function(error) {
        console.log(error);
      });
  };