React 上下文在超时中不是最新的

React context not being up to date in a Timeout

我正在使用 React 应用程序上下文来存储一组“警报对象”,这基本上是可能发生的任何错误,我想在网站的右上角显示。我遇到的问题是上下文在超时内没有更新。我为测试所做的是获得一个按钮,在单击时将警报对象添加到上下文,另一个组件映射到上下文中的该数组并呈现它们。我希望它们在 5 秒后消失,所以我添加了一个超时来过滤刚刚添加的项目并将其删除。问题是在超时内 context.alerts 数组似乎与 5 秒前具有相同的值,而不是使用导致问题和元素未被过滤掉的最新值。我不确定我的逻辑是否有问题,或者我是否使用了错误的上下文?

        onClick={() => {
          const errorPopup = getPopup(); // Get's the alert object I need
          context.setAlerts([errorPopup, ...context.alerts]);
          setTimeout(() => {
            context.setAlerts([
              ...context.alerts.filter(
                (element) => element.id !== errorPopup.id,
              ),
            ]);
          }, 5000);
        }}

我认为解决方法是将 context.setAlerts(...) 移动到一个单独的函数(比如 removePopupFromContext(id:string)),然后通过传递 errorPopup.Id作为参数。

我不确定你对 context.setAlerts 的实现,但如果它仅基于 setState 函数,那么你也可以做一些类似于 React 让你使用函数访问 setState 中的 prevState 的事情这将使您跳过额外功能的创建,该功能可能会轻微转化为:

setContext(prevContextState =>({
  ...prevContextState, 
  alerts: prevContextState.alerts.filter(your condition)
)})
onClick={() => {
          const errorPopup = getPopup(); // Get's the alert object I need
          context.setAlerts([errorPopup, ...context.alerts]);
          setTimeout(() => {
            context.setAlerts(alerts => [
              ...alerts.filter(
                (element) => element.id !== errorPopup.id,
              ),
            ]);
          }, 5000);
        }}

这应该可以解决问题。在 react@17 之前,事件处理程序中的 setStates 被批处理(在 react@18 中,所有 setStates 甚至是异步的都被批处理),因此您需要使用最新的状态在第二个进行更新setAlerts.

为了安全起见,最好在第一个 setState 中使用 cb 语法。