javascript 从JS过渡到React:我怎样才能预先添加一个元素,然后在一段时间后删除它?

mmvthczy  于 2023-03-16  发布在  Java
关注(0)|答案(1)|浏览(124)

我有一个用javascript写的小项目,我正试图用React重写它。我有一个警报部分,我在那里预先添加了一条消息,这样它就出现在列表的顶部,然后在5秒后被删除。
超文本:

<div id="alert-container">
    <button onclick="addAlert('alert')">Add</button>
</div>

联森:

function addAlert(message) {
    const alertContainer = document.getElementById("alert-container")

    const alert = document.createElement("div")
    alert.textContent = message
    alertContainer.prepend(alert)
    setTimeout(() => {
        alert.remove()
    }, 5000)
}

我遇到的问题是不知道如何“prepend”React元素,我可以创建一个包含警报消息列表的状态,然后为每个警报消息添加一个新的状态,但我遇到了两个问题:
1.如何设置计时器,以便在5秒后删除实际的React元素
1.当需要删除消息时,如何将其从消息列表中删除?我想我可以添加一个show:true属性,然后在每个警报超时后将其设置为false,但我不确定这是否是理想的方法,因为它似乎有点过于复杂。
我觉得这应该是相对简单的做像在JS我有以上,但我真的找不到一个简单的方法来做到这一点。
谢谢!

ufj5ltwl

ufj5ltwl1#

我遇到的问题是我不知道如何“prepend”React元素,我可以创建一个包含警报消息列表的状态,然后为每个警报消息添加一个新的
是的,这就是你要做的,你将有一个数组作为你的状态,然后为了预先计划一个新的警报,你将添加到那个数组的前面。
如何设置计时器,以便在5秒后删除实际的React元素
您可以在更改阵列后立即设置超时
当需要删除邮件时,如何从邮件列表中删除该邮件?
当计时器停止计时时,你将设置状态并从数组中删除警报。假设计时器都正好是5秒,你的警报将移动到数组的末尾,所以你可以只删除数组中的最后一个元素。

import { useState } from 'react';

const AlertContainer = () => {
  const [alerts, setAlerts] = useState([]);

  const addAlert = (message) => {
    setAlerts(prev => [message, ...prev]);
    setTimeout(() => {
      setAlerts(prev => {
        const next = [...prev];
        next.pop();
        return next; 
      });
    }, 5000);
  }

  return (
    <div>
      {alerts.map((message, i) => (
        <div key={i}>{message}</div>
      ))}
      <button onClick={() => addAlert('alert')}>Add</button>
    </div>
  )
}

另一个问题是,如果我想让这些单独的div淡出,有没有一种对React友好的方法可以做到这一点?
为此,您需要一个更复杂的状态。现在,每个警报由两个数据段定义:它是消息,以及它是否应该淡出。这也意味着数组中的最后一个元素可能还没有准备好从页面中删除,所以我将为每个警报添加一个唯一的id,以便我可以在数组中找到它们:

import { useState } from "react";

let uniqueId = 0;

const AlertContainer = () => {
  const [alerts, setAlerts] = useState([]);

  const addAlert = (message) => {
    uniqueId += 1;
    const id = uniqueId;
    setAlerts((prev) => [{ id, message, fadeOut: false }, ...prev]);
    setTimeout(() => {
      setAlerts((prev) => {
        const next = [...prev];
        const i = next.findIndex((alert) => alert.id === id);
        next[i] = { ...next[i], fadeOut: true };
        return next;
      });
    }, 5000);
  };

  return (
    <div>
      {alerts.map((alert) => (
        <div
          key={alert.id}
          className={alert.fadeOut ? "fadeOut" : undefined}
          onTransitionEnd={() => {
            setAlerts((prev) => prev.filter((a) => a.id !== alert.id));
          }}
        >
          {alert.message}
        </div>
      ))}
      <button onClick={() => addAlert("alert")}>Add</button>
    </div>
  );
};

随着复杂性的增加,您可能希望创建一个单独的<Alert>组件,并让它处理额外的状态片段,例如,这里我将定时器和淡出逻辑的职责移到子组件中:

import { useState, useEffect } from "react";

let id = 0;

const AlertContainer = () => {
  const [alerts, setAlerts] = useState([]);

  const addAlert = (message) => {
    id += 1;
    setAlerts((prev) => [{ id, message }, ...prev]);
  };

  return (
    <div>
      {alerts.map((alert) => (
        <Alert
          key={alert.id}
          message={alert.message}
          remove={() => {
            setAlerts((prev) => prev.filter((a) => a.id !== alert.id));
          }}
        />
      ))}
      <button onClick={() => addAlert("alert")}>Add</button>
    </div>
  );
};

const Alert = ({ message, remove }) => {
  const [fadeOut, setFadeOut] = useState(false);
  useEffect(() => {
    setTimeout(() => {
      setFadeOut(true);
    }, 5000);
  }, []);

  return (
    <div
      className={fadeOut ? "fadeOut" : undefined}
      onTransitionEnd={remove}
    >
      {message}
    </div>
  );
};

相关问题