错误 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]);
工作演示:
我试图让错误在 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]);
工作演示: