当前位置: 首页 > 知识库问答 >
问题:

理解反应效应函数。何时调用useffect中的回调函数(即unsubscribe)?

严宇
2023-03-14

我一直在试图理解什么时候取消订阅(在use效应中的回调)会被准确地调用。

这是代码笔链接:https://codepen.io/deen_john/pen/eYmNdMy代码:

const { useState, useEffect } = React  ;
 
function App() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
    console.log("use effect called ");
    
    return () => {
      console.log("unsubscribe ")
    }
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

问题:在我的例子中,使用效果钩子中的回调函数(即取消订阅),每次我点击按钮时都会被调用(即每次我更新按钮状态)。但是,根据React留档,use效应中的回调工作类似于组件WillUnMount生命周期,所以在我的例子中,它应该只有在应用组件被卸载时才被调用。我只是在这里更新按钮状态,而不是在每次点击时卸载应用程序组件。

共有2个答案

潘宪
2023-03-14

React将始终尝试更新您的效果。因此,无论何时运行,默认情况下都会尝试清理最后一个效果以应用新效果。

  • 每次渲染后运行的效果

因此,如果效果在每次渲染后运行,React将在每次渲染后清理,然后应用新效果。

  • 基于某些依赖项运行的效果

如果效果取决于某些变量(包含在依赖项数组[a、b等]中)来决定是否应再次运行,同样的情况也会发生。如果它将再次运行,React将在运行效果之前运行清理函数。

  • 仅在第一次渲染后运行的效果

如果效果仅在第一次渲染后运行(使用空的依赖项数组[]),则React仅在卸载组件后执行清理。

例子:

下面的片段显示了该行为。

function App() {
  console.log('Rendering App...');
  const [show2,setShow2] = React.useState(true);
  const [stateBool,setStateBool] = React.useState(true);
  return(
    <React.Fragment>
      <button onClick={()=>{
        console.clear();
        setStateBool((prevState)=>!prevState)}
      }>
        Update App
      </button>
      <button onClick={()=>{
        console.clear()
        setShow2((prevState)=>!prevState)}
      }>
        Toggle Component2
      </button>
      <Component1/>
      {show2 && <Component2/>}
    </React.Fragment>
  );
}

function Component1() {
  console.log('Rendering Component1...');
  React.useEffect(()=>{
    console.log('useEffect Component1 after every render...');
    return () => console.log('Cleaning up useEffect Component1...');
  });
  return(
    <div>Component1</div>
  );
}

function Component2() {
  console.log('Rendering Component2...');
  React.useEffect(()=>{
    console.log('useEffect Component2 only after 1st render...');
    return () => console.log('Cleaning up useEffect Component2...');
  },[]);
  return(
    <div>Component2</div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
html prettyprint-override"><script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
吴哲
2023-03-14

每次在下次调用useEffect之前以及组件卸载时,都会调用useEffect的unsubscribe事件

因为在您的情况下,您没有将任何依赖项数组传递给useEffect,所以useEffect将在组件的每个渲染上运行,因此在触发下一个useEffect之前,取消订阅将在每次重新渲染上运行

编写上述代码的更好方法是将依赖项数组中的count传递给useffect

const { useState, useEffect } = React;
 
function App() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
    console.log("use effect called ");
    
    return () => {
      console.log("unsubscribe ")
    }
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
 类似资料:
  • 本文向大家介绍理解javascript回调函数,包括了理解javascript回调函数的使用技巧和注意事项,需要的朋友参考一下 把函数作为参数传入到另一个函数中。这个函数就是所谓的回调函数 经常遇到这样一种情况,某个项目的A层和B层是由不同的人员协同完成.A层负责功能funA,B层负责funcB。当B层要用到某个模块的数据,于是他对A层人员说,我需要你们提供满足某种需求的数据,你给我提供一个接口。

  • 我试图转换一个简单的React组件与一个this.setstate回调到一个功能组件与useState/使用效果,但我不能复制相同的功能与后者。 我正在使用一个简单警报/通知系统的示例来在超时后追加和删除警报。沙箱: https://codesandbox.io/s/class-and-function-callback-comparison-54tus?file=/src/index.js 相关

  • 本文向大家介绍理解javascript中的回调函数(callback),包括了理解javascript中的回调函数(callback)的使用技巧和注意事项,需要的朋友参考一下 最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用。如果这个概念理解不了,nodejs、express 的代码就会看得一塌糊涂。比如: app是对象,use是方法,方法的参数是一个带参的匿名函数,函数体

  • 本文向大家介绍JS回调函数深入理解,包括了JS回调函数深入理解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS回调函数。分享给大家供大家参考,具体如下: 一、前奏 在谈回调函数之前,先看下下面两段代码: 不妨猜测一下代码的结果。 如果你测试了,就会发现: 只写变量名  say   返回的将会是 say方法本身,以字符串的形式表现出来。 而在变量名后加()如say()返回的就会使say方

  • 我正在尝试使用react钩子创建一个悬停以显示div,我遇到了以下问题: 第69:31行:在函数“renderHideOptionalClauseTrigger”中调用React钩子“useState”,该函数既不是React函数组件,也不是自定义React钩子函数React钩子/钩子规则 搜索关键字以了解有关每个错误的更多信息。 以下是我的代码库:

  • 回调函数 返回上级 DDEnumCallback DDEnumCallbackEx EnumModesCallback EnumSurfacesCallback EnumVideoCallback DDEnumCallback 返回目录 DDEnumCallback是用于DirectDrawEnumerate函数的应用程序定义的回调函数。 BOOL WINAPI DDEnumCallback( G