react useEffect中removeEventListener没生效问题解决

文章讲述了在React组件中使用useEffect添加和移除resize事件监听器时,如果不正确处理,会导致事件监听未生效。原因是React的更新机制使得回调函数在每次渲染时都可能是新创建的。解决方法是使用useCallback或useRef来确保回调函数在更新时被缓存或保持不变。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在useEffect中写入window.removeEventListener没有生效,代码如下

useEffect(() => {
  const handleResize = () => {
  	console.log(window.innerWidth, window.innerHeight);
  };
  window.addEventListener('resize', handleResize);
  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, [);

没生效原因:
在 removeEventListener 中所传递回的调函数需要与 addEventListener 中的保持一致,而在react中,因为视图更新所产生的更改,导致在return时所传递的函数是最新创建的函数,而不是在addEventListener中所传递的,简单来说就是react的更新机制所导致的引用问题。

解决方法:
使用useCallback来缓存一个函数,避免在每次渲染时重新创建这个函数。
也可以用useRef定义一个函数,确保函数在重新渲染是不被重新创建。

const handleResize = useCallback(() => {
  console.log(window.innerWidth, window.innerHeight);
}, []);
 
useEffect(() => {
  window.addEventListener('resize', handleResize);
  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, [);
### 条件渲染的概念及实现方式 条件渲染是指根据某些特定的条件来动态决定是否渲染某个组件或元素。在 React 中,可以使用 JavaScript 的条件语句(如 `if`、三元运算符等)进行条件渲染。例如: ```jsx render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> {isLoggedIn ? <LogoutButton /> : <LoginButton />} </div> ); } ``` 通过这种方式,可以根据用户的状态动态切换不同的 UI 组件[^1]。 ### 如何优化 React 应用性能 优化 React 应用性能可以从多个方面入手: - **减少不必要的渲染**:使用 `React.memo` 或 `PureComponent` 来避免不必要的重新渲染。 - **代码分割**:利用 React 的 `lazy` 和 `Suspense` 特性将代码拆分成更小的部分,按需加载。 - **防抖与节流**:对于高频触发的事件(如滚动、窗口调整大小),可以通过防抖和节流技术减少调用频率,从而提高性能。 以下是一个使用 Lodash 的 `throttle` 函数实现节流的例子: ```jsx import React, { useState, useEffect } from 'react'; import { throttle } from 'lodash'; const ScrollComponent = () => { const [scrollPosition, setScrollPosition] = useState(0); const handleScroll = throttle(() => { setScrollPosition(window.pageYOffset); }, 300); useEffect(() => { window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, [handleScroll]); return ( <div> <p>Scroll Position: {scrollPosition}px</p> <div style={{ height: '2000px' }}>Scroll me!</div> </div> ); }; export default ScrollComponent; ``` 通过这种方式,可以有效地控制滚动事件的触发频率,提升应用性能[^2]。 ### CSS 样式优先级规则 在 CSS 中,样式的优先级决定了哪些样式会被最终应用到元素上。具体规则如下: - `!important` 声明的样式的优先级最高。 - 如果优先级相同,则最后出现的样式生效。 - 继承得到的样式的优先级最低。 - 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式。 这些规则帮助开发者理解不同情况下样式的应用情况,有助于解决样式冲突问题[^3]。 ### React 前端开发面试常见问题及答案解析 1. **什么是虚拟 DOM?** 虚拟 DOM 是一个轻量级的 JavaScript 对象,它是真实 DOM 的抽象表示。当数据发生变化时,React 会先更新虚拟 DOM,然后通过 Diffing 算法比较新旧虚拟 DOM 的差异,并仅更新需要改变的部分,从而提高性能。 2. **React Hooks 是什么?** React Hooks 是 React 16.8 引入的新特性,允许在函数组件中使用状态和其他 React 特性。常用的 Hook 包括 `useState`、`useEffect` 等。 3. **如何处理 React 中的数据流?** React 推荐使用单向数据流模型。父组件通过 props 向子组件传递数据,子组件通过回调函数通知父组件数据的变化,这样可以保持数据的一致性和可预测性。 4. **React 中的上下文(Context)是什么?** Context 提供了一种在组件树中传递数据的方式,而无需手动地通过每一层组件传递 props。这对于全局共享的数据非常有用,但应谨慎使用以避免过度复杂化。 5. **React 中的错误边界是什么?** 错误边界是一种 React 组件,它可以捕获并处理其子组件树中的 JavaScript 错误。它会显示降级 UI 而不是崩溃整个应用。错误边界只能捕获后代组件构造函数、生命周期方法以及渲染过程中发生的错误。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值