Zhe*_*Bai 6 javascript reactjs react-hooks use-effect
我问这个问题是为了确认我对某些概念的理解。
React 文档强调包含 useEffect() 回调中使用的所有依赖项。正如文档中所解释的:
我有点明白这个解释是从哪里来的。但我关心的是“陈旧价值”部分。我没有看到由于缺少依赖项而导致过时值发生任何可能的方式。我的论点也得到了文档中内容的支持:
经验丰富的 JavaScript 开发人员可能会注意到,传递给 useEffect 的函数在每次渲染时都会有所不同。这是故意的。事实上,这让我们可以从效果内部读取计数值,而不必担心它会过时。
据我的理解,如果我们错过列出依赖项,则该效果将不会在该依赖项更改引起的渲染后运行,因为 React 认为效果不依赖于它。如果我猜测,可能是文档提到引用过时数据时的情况。事实上,效果代码中的数据已经过时。但是,效果回调一开始并不运行。在效果运行之前我不会注意到数据已过时。如果这很重要,我将首先找出效果未运行的原因并解决问题。我感到困惑的不是数据过时,而是效果无法运行。
此外,我们假设效果在由另一个依赖项更改引起的渲染之后运行。在这种情况下,即使我们错过了依赖项,由于上述关闭原因,我们也不会读取过时的数据。我做了一些实验来证实这一点:
export default function App() {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(10);
useEffect(() => {
console.log(count2);
}, [count1]);
return (
<div className="App">
<div>
Count1: {count1}
<button onClick={() => setCount1(count1 + 1)}>increase</button>
</div>
<div>
Count2: {count2}
<button onClick={() => setCount2(count2 + 1)}>increase</button>
</div>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
只要效果运行,我们总是会得到最新的 count2。那么我的理解成立吗?
我想知道为什么 React 如此推荐包含所有依赖项。人们通常使用依赖数组来绕过某些运行效果。如果他们省略了依赖项,这可能就是他们想要的。如果是失误,他们很容易注意到效果没有运行并采取行动。
我稍微修改了您的示例以显示陈旧的值。
效果通常出于异步原因而使用,因此这并不罕见。
基本上它取决于闭包,useEffect 的第一次渲染将在 count1 和 count2 上创建一个闭包,如果效果没有在所有依赖项上重新运行,那么这些闭包将保持(陈旧)。
单击count1then 意味着再次调用 useEffect,创建 setInterval 的新实例,并使用 count1 和 count2 的新(非陈旧)副本。因为 count2 不在依赖数组中,所以单击count2将意味着不会创建新的 setInterval,并且 count1 和 count2 的过时副本将保留在内存中。
公平地说,这可能是 Hooks 中难以理解的一个领域。很容易将 Hook 组件视为对象的一部分,其中包含数据的类。但实际上钩子组件只是渲染函数,useState / useEffect 等是侧面加载到渲染函数管道中的。相比之下,React 类组件的数据与对象实例一起存储,因此this.xyz永远不会过时。
const {useState, useEffect} = React;
function App() {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(10);
useEffect(() => {
const tm = setInterval(() => {
console.log(count1, count2);
}, 1000);
return () => clearInterval(tm);
}, [count1]);
return (
<div className="App">
<div>
Count1: {count1}
<button onClick={() => setCount1(count1 + 1)}>increase</button>
</div>
<div>
Count2: {count2}
<button onClick={() => setCount2(count2 + 1)}>increase</button>
</div>
</div>
);
}
ReactDOM.render(<App/>,document.querySelector('#mount'));Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="mount"></div>
<p>Increase count2, see the console not update until you increase count1,.</p>
<p>Add count2 to the dependancy, and then everything will keep in sync</p>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
239 次 |
| 最近记录: |