为了账号安全,请及时绑定邮箱和手机立即绑定

React set出错时3秒后超时

React set出错时3秒后超时

守着星空守着你 2022-08-18 10:31:24
我试图让错误在3秒后从State数组中删除自己,它有点工作,但由于某种原因,它会跳回去并表现得很奇怪/删除多个1超时完成。(请参阅错误功能组件)。我使用 React 上下文进行状态管理,并希望我能得到任何帮助。我将不胜感激任何帮助你可以在这里实时查看错误:https://codesandbox.io/s/flamboyant-jackson-soutv?file=/src/components/Errors.jsx:558-567Errors.jsximport { 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;
查看完整描述

2 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

您的代码有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);

  }, []);

第二:传递索引,而不是ierror.id


// here you are passing index, instead of error.id

<Error id={i} error={error.message} />;

第一个问题的解决方案是这个做阅读:


  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]);


查看完整回答
反对 回复 2022-08-18
?
波斯汪

TA贡献1811条经验 获得超4个赞

您必须在卸载时清除超时。由于你不清楚,所以每次新的超时声明。


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


查看完整回答
反对 回复 2022-08-18
  • 2 回答
  • 0 关注
  • 109 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信