首页 > 解决方案 > 从 ReactJS 中的 dom 中删除动态渲染元素

问题描述

目前我有一个看起来像这样的反应组件:

const GeraCard = (cards, cart = false) => {
    return cards.map((v, i) => {
      return (
        <div key={i} className={styles.card}>
          <div onClick={() => urlRender(v.url)} className={styles.cardContent}>
            <div>
              <span className={styles.cardTitulo}>{v.Nome}</span>
            </div>
            <div>
              <span className={styles.cardData}>{v.Data}</span>
              <span className={styles.cardAtivos}>{v.Ativos} ativo(s)</span>
            </div>
            {cart ? <div>R$ {FormatCapital(v.Capital)}</div> : null}
          </div>
          <span className={styles.trash}>
            <FontAwesomeIcon
              icon={faTrash}
              color={"#3c3c3c77"}
              onClick={(e) => {
                e.persist()
                TrashHandler(v.Nome, e)
              }}
            />
          </span>
        </div>
      );
    });
  };

基于卡片数组,它呈现如下内容:

渲染组件

每当我单击垃圾桶按钮时,我都会向后端发出请求,编辑数据库中的列表并根据现在更新的“卡片”重新呈现组件。问题是这需要一段时间才能发生,所以我想要一种方法在我的后端完成它的工作时立即从 dom 中删除它。

有点像

{show ? renderCompoennt : null}

我尝试使用香草 javascript 从垃圾桶中抓取父级,这将是我要删除的卡,但结果是不可预测的,而且速度也很慢。

我最近的尝试是这样的:

const GeraCard = (cards, cart = false) => {
    return cards.map((v, i) => {
      const [show, setShow] = useState(true);
      return (
        <div key={i}>
          {show ?
            <div className={styles.card}>
              <div onClick={() => urlRender(v.url)} className={styles.cardContent}>
                <div>
                  <span className={styles.cardTitulo}>{v.Nome}</span>
                </div>
                <div>
                  <span className={styles.cardData}>{v.Data}</span>
                  <span className={styles.cardAtivos}>{v.Ativos} ativo(s)</span>
                </div>
                {cart ? <div>R$ {FormatCapital(v.Capital)}</div> : null}
              </div>
              <span className={styles.trash}>
                <FontAwesomeIcon
                  icon={faTrash}
                  color={"#3c3c3c77"}
                  onClick={(e) => {
                    setShow(false);
                    e.persist()
                    TrashHandler(v.Nome, e)
                  }}
                />
              </span>
            </div> :
            null
          }
        </div>
      );
    });
  };

但反应不会让我这样做。即使它很快,每次删除一个项目时,react 都会抱怨“渲染的钩子更少”并使应用程序崩溃。

标签: javascriptreactjsdom-manipulation

解决方案


您正在尝试做一些Optimistic UI,其中您假设您的操作将成功,并在对后端的请求完成之前立即反映预期/假定的状态。这将代替显示一些进度/忙碌指示器,如微调器,直到服务器完成操作。

代码中的第一个问题和直接问题——它违反了hooks 的规则,该规则规定 hooks只能在顶层使用(永远不能在循环、条件等内部)。

第二个问题是您正在利用 vanilla JS 直接操作 DOM;这通常是 MV* 框架中的反模式,在这里也是如此。相反,我建议在您的数据模型中进行管理;像这样的东西:

  1. 如果卡具有属性,则重写您的.map处理程序以返回。nulldeleted
  2. 当用户点击垃圾桶按钮时,做两件事:
    1. 向后端发出请求以删除它
    2. 使用 asetStatedeleted: true属性添加到点击的卡片

现在您将获得一个重新渲染,它将忽略已删除的卡片,并向后端发出请求,所有这些都在 React 数据模型中。确保您处理以下复杂性:

  1. 如何处理响应
  2. 后台删除失败如何处理错误
  3. 如果用户在任何请求完成之前快速单击许多卡片进行删除,如何进行管理。

推荐阅读