错误 3 秒后响应 setTimeout

React setTimeout after 3 seconds on Error

我试图让错误在 3 秒后从 State 数组中自行删除,这有点奏效,但由于某种原因,它跳回并在 1 次超时完成时执行 weird/removes 多次操作。 (在错误功能组件中看到)。

我在状态管理中使用 React 上下文,如果能得到任何帮助,我将不胜感激。

如有任何帮助,我将不胜感激

您可以在此处实时查看错误:https://codesandbox.io/s/flamboyant-jackson-soutv?file=/src/components/Errors.jsx:558-567

Errors.jsx

import { SiteContext } from "../context/SiteContext";

const Error = props => {
  const [siteSettings, setSiteSettings] = useContext(SiteContext);
  let errors = siteSettings.errors;
  console.log("Errors", errors);
  let filteredAry = errors.filter(function(obj) {
    return obj.id !== props.id;
  });
  //removed last id , and filteredArray is where we store the new array
  console.log("Filtered array", filteredAry);
  //after 3 seconds we should update the old array with the new array
  useEffect(() => {
    setTimeout(() => {
      setSiteSettings(siteSettings => ({
        ...siteSettings,
        errors: filteredAry
      }));
    }, 3000);
  }, []);

  return <div className="error">{props.error}</div>;
};

const Errors = () => {
  const [site, setSiteSettings] = useContext(SiteContext);
  const addError = () => {
    //find the latest id
    let max = 0;
    if (site.errors.length > 0) {
      max = Math.max.apply(null, site.errors.map(item => item.id)) + 1;
    } else {
      max = 1;
    }
    console.log("Highest id: " + max);
    //add new error to the State,
    setSiteSettings(site => ({
      ...site,
      errors: [...site.errors, { message: "Some error", id: max }]
    }));
  };
  return (
    <div id="errors">
      Error page
      {site.errors.map((error, i) => {
        return <Error id={i} error={error.message} />;
      })}
      <button onClick={addError}>Add error</button>
    </div>
  );
};

export default Errors;

App.js

import "./styles.css";
import { SiteProvider } from "./context/SiteContext";
import Errors from "./components/Errors";

export default function App() {
  return (
    <SiteProvider>
      <div className="App">
        Errors : <Errors />
      </div>
    </SiteProvider>
  );
}

SiteContext.jsx


export const SiteContext = createContext();

export const SiteProvider = props => {
  const [siteSetting, setSiteSetting] = useState({
    errors: []
  });

  return (
    <SiteContext.Provider value={[siteSetting, setSiteSetting]}>
      {props.children}
    </SiteContext.Provider>
  );
};

最好的问候,丹尼尔。

您必须清除卸载超时。由于您不清楚,因此每次都声明新的超时。

useEffect(() => {
    const id = setTimeout(() => {
      setSiteSettings(siteSettings => ({
        ...siteSettings,
        errors: filteredAry
      }));
    }, 3000);
    return () => clearTimeout(id);
  }, []);

您可以像服务一样创建它,可以根据时间戳删除旧消息:

这里id是消息创建时的时间戳。

片段:

import React, { useState, useEffect } from "react";
import "./styles.css";
const Errors = () => {
  const [errors, setErrors] = useState([]);
  const [counter, setCounter] = useState(0);
  useEffect(() => {
    const timerId = setInterval(() => {
      if (counter < 10) {
        const id = new Date().getTime();
        // stop generating
        setErrors(ee => ee.concat({ id, message: "Error: " + new Date() }));
      }

      setCounter(counter + 1);
    }, 1000);
    return clearInterval.bind(this, timerId);
  }, [counter]);
  /// clear error
  useEffect(() => {
    const timerId = setInterval(() => {
      setErrors(ee => {
        return ee.filter(({ id }) => new Date().getTime() - id < 3000);
      });
    }, 2000);
    return clearInterval.bind(this, timerId);
  }, []);
  return (
    <ul>
      {errors.map(({ id, message }, i) => {
        return <li key={id}>{message}</li>;
      })}
    </ul>
  );
};
export default function App() {
  return (
    <div className="App">
      <Errors />
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

请检查一个粗略的样本:

https://codesandbox.io/s/quiet-dream-mzcmm?file=/src/App.js:0-1084

您的代码存在 2 个主要问题

首先:不更新最新状态,更新差异旧状态

 let errors = siteSettings.errors;
  console.log("Errors", errors);
  // Will provide the old errors, not the updated once
  // so each time you add new error, you will get diff filtered array
  // for 1 you get 0
  // for 2 you get 1
  // ....
  let filteredAry = errors.filter(function(obj) {
    return obj.id !== props.id;
  });
  useEffect(() => {
    setTimeout(() => {
      setSiteSettings(siteSettings => ({
        ...siteSettings,
        errors: filteredAry
      }));
    }, 3000);
  }, []);

第二个: 传递索引 i,而不是 error.id

// here you are passing index, instead of error.id
<Error id={i} error={error.message} />;

第一个问题的解决方案是 DO READ :

  useEffect(() => {
    const id = setTimeout(() => {
      setSiteSettings(siteSettings => {
        // get latest copy of state `siteSettings `
        // and work on that
        let filteredAry = siteSettings.errors.filter(function(obj) {
          return obj.id !== props.id;
        });        
        return {
          ...siteSettings,
          errors: filteredAry
      }});
    }, 3000);
    return () => clearTimeout(id);
  }, [props.id]);

工作演示: