React set出错时3秒后超时

我试图让错误在3秒后从State数组中删除自己,它有点工作,但由于某种原因,它会跳回去并表现得很奇怪/删除多个1超时完成。(请参阅错误功能组件)。


我使用 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;


守着星空守着你
浏览 110回答 2
2回答

慕雪6442864

您的代码有2个主要问题:第一:不更新最新状态,并更新差异旧状态&nbsp;let errors = siteSettings.errors;&nbsp; console.log("Errors", errors);&nbsp; // Will provide the old errors, not the updated once&nbsp; // so each time you add new error, you will get diff filtered array&nbsp; // for 1 you get 0&nbsp; // for 2 you get 1&nbsp; // ....&nbsp; let filteredAry = errors.filter(function(obj) {&nbsp; &nbsp; return obj.id !== props.id;&nbsp; });&nbsp; useEffect(() => {&nbsp; &nbsp; setTimeout(() => {&nbsp; &nbsp; &nbsp; setSiteSettings(siteSettings => ({&nbsp; &nbsp; &nbsp; &nbsp; ...siteSettings,&nbsp; &nbsp; &nbsp; &nbsp; errors: filteredAry&nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }, 3000);&nbsp; }, []);第二:传递索引,而不是ierror.id// here you are passing index, instead of error.id<Error id={i} error={error.message} />;第一个问题的解决方案是这个做阅读:&nbsp; useEffect(() => {&nbsp; &nbsp; const id = setTimeout(() => {&nbsp; &nbsp; &nbsp; setSiteSettings(siteSettings => {&nbsp; &nbsp; &nbsp; &nbsp; // get latest copy of state `siteSettings `&nbsp; &nbsp; &nbsp; &nbsp; // and work on that&nbsp; &nbsp; &nbsp; &nbsp; let filteredAry = siteSettings.errors.filter(function(obj) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return obj.id !== props.id;&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...siteSettings,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errors: filteredAry&nbsp; &nbsp; &nbsp; }});&nbsp; &nbsp; }, 3000);&nbsp; &nbsp; return () => clearTimeout(id);&nbsp; }, [props.id]);

波斯汪

您必须在卸载时清除超时。由于你不清楚,所以每次新的超时声明。useEffect(() => {&nbsp; &nbsp; const id = setTimeout(() => {&nbsp; &nbsp; &nbsp; setSiteSettings(siteSettings => ({&nbsp; &nbsp; &nbsp; &nbsp; ...siteSettings,&nbsp; &nbsp; &nbsp; &nbsp; errors: filteredAry&nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }, 3000);&nbsp; &nbsp; return () => clearTimeout(id);&nbsp; }, []);您可以像服务一样创建它,可以根据时间戳删除旧的消息:下面是创建消息时的时间戳。id片段:import React, { useState, useEffect } from "react";import "./styles.css";const Errors = () => {&nbsp; const [errors, setErrors] = useState([]);&nbsp; const [counter, setCounter] = useState(0);&nbsp; useEffect(() => {&nbsp; &nbsp; const timerId = setInterval(() => {&nbsp; &nbsp; &nbsp; if (counter < 10) {&nbsp; &nbsp; &nbsp; &nbsp; const id = new Date().getTime();&nbsp; &nbsp; &nbsp; &nbsp; // stop generating&nbsp; &nbsp; &nbsp; &nbsp; setErrors(ee => ee.concat({ id, message: "Error: " + new Date() }));&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; setCounter(counter + 1);&nbsp; &nbsp; }, 1000);&nbsp; &nbsp; return clearInterval.bind(this, timerId);&nbsp; }, [counter]);&nbsp; /// clear error&nbsp; useEffect(() => {&nbsp; &nbsp; const timerId = setInterval(() => {&nbsp; &nbsp; &nbsp; setErrors(ee => {&nbsp; &nbsp; &nbsp; &nbsp; return ee.filter(({ id }) => new Date().getTime() - id < 3000);&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }, 2000);&nbsp; &nbsp; return clearInterval.bind(this, timerId);&nbsp; }, []);&nbsp; return (&nbsp; &nbsp; <ul>&nbsp; &nbsp; &nbsp; {errors.map(({ id, message }, i) => {&nbsp; &nbsp; &nbsp; &nbsp; return <li key={id}>{message}</li>;&nbsp; &nbsp; &nbsp; })}&nbsp; &nbsp; </ul>&nbsp; );};export default function App() {&nbsp; return (&nbsp; &nbsp; <div className="App">&nbsp; &nbsp; &nbsp; <Errors />&nbsp; &nbsp; &nbsp; <h2>Start editing to see some magic happen!</h2>&nbsp; &nbsp; </div>&nbsp; );}请检查粗略样品:https://codesandbox.io/s/quiet-dream-mzcmm?file=/src/App.js:0-1084
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript