react-hooks知识梳理—3.useRef

本文探讨了React Hooks中useEffect和useRef的使用问题。针对useEffect在实现定时器时可能出现的count值捕获问题,提出了利用useRef作为变量来保持状态的持久性。同时,解释了useRef如何用于获取DOM元素和处理原生事件,以及在避免直接操作DOM时的优势。此外,还提到了useRef在处理复杂场景中的其他功能。

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

1.回忆useEffect的问题

————————————————————————————————————————————————

想实现一个定时器的效果,每0.5s count加1

import React, { useState, useEffect } from 'react';
 
const Fetch = () => {
  const [count, setCount] = useState(0);
 
  useEffect(() => {
    setInterval(() => {
      setCount(count + 1 );
    }, 500);
  }, []);
 
  return (
    <div>
      count: {count}
    </div>
  )
};
 
function UseEffect() {
  return (
    <div className="App">
      <Fetch />
    </div>
  );
}
 
export default UseEffect;

但是执行一下,加了1就不动了

因为useEffect有一个特性是catpurrvalue,,就是没有任何依赖的情况下,会捕获初始传进来的值,后面不会在变化。所以看下面控制台里面每次打印都是0。

————————————————————————————————————————————————

useEffect添加一个依赖,这样依赖变化的时候,他就会跟着变化,有一个问题就是useEffect每次都会重新执行,即会产生一起新的回调,往往有时候不希望一些useEffect去执行,不执行的话就是不去添加依赖,但不添加依赖的话由于特性catpurrvalue,依赖的值可能是旧的,这样就会导致一个bug。这个时候useRef就登场了。

2.useRef功能一:作为变量

可以尝试用useRef解决上面的问题

import React, { useState, useEffect, useRef } from 'react';

const Fetch = () => {
  const [count, setCount] = useState(0);
  const countRef = useRef(null);

  useEffect(() => {
    countRef.current = count + 1;
  }, [count]);

  useEffect(() => {
    const timer = setInterval(() => {
      console.log(count, countRef.current);
      setCount(countRef.current);
    }, 500);
    return () => clearInterval(timer);
  }, []);

  return (
    <div>
      count: {count}
    </div>
  )
};

function UseRef() {
  return (
    <div className="App">
      <Fetch />
    </div>
  );
}

export default UseRef;

理解一下,useRef里面的crrent是在组件整个生命周期中,不会随着state的变化而变化,可以理解为组件内部的一个全局变量,其他地方都可以访问到他的最新值,除非手动的给他变化,即countRef.current = count这样。而state在useEffect里面,是有capturevalue的,不一定访问到他的最新值,除非添加依赖

3.useRef功能二:获取dom

import React, { useState, useEffect, useRef } from 'react';

const Fetch = () => {
  const [count, setCount] = useState(0);
  const btnRef = useRef(null);

  useEffect(() => {
    const handleOnClick = () => {
      setCount(count + 1);
    };
    btnRef.current.addEventListener('click', handleOnClick, false);
    return () => {
      btnRef.current.removeEventListener('click', handleOnClick, false);
    };
  }, [count]);

  return (
    <div>
      count: {count}
      <br/>
      <button ref={btnRef}>+1</button>
    </div>
  )
};

function UseRef() {
  return (
    <div className="App">
      <Fetch />
    </div>
  );
}

export default UseRef;

3.useRef其他功能

react实现了一些自己的事件,但他并没有覆盖全部的原生dom事件,比如说onClick事件是有的,但鼠标滚动的事件的一些事件是没有的,这样就需要自己使用dom去绑定,这个时候useRef就派上用场了。

当然可以通过绑定id的方式获取dom,但是这种方式存在一个问题,给人感觉你是直接在操作dom。而使用useRef方式并不是直接操作dom,操作dom被放在react内部了,并没有对你的程序代码造成破坏。

 

 

<think>嗯,用户想要了解React Hooks的笔记,我需要整理一个结构清晰的回答。首先,我得回忆一下React Hooks的核心内容和常见钩子。React Hooks是在React 16.8引入的,允许函数组件使用状态和其他React特性,这样就不用写类组件了。对吧? 那应该先介绍Hooks的基本概念,比如为什么需要Hooks,解决了类组件的哪些问题,比如复杂的生命周期和this绑定问题。然后分点讲常用的内置Hooks,比如useState、useEffect、useContext这些。每个Hook要解释作用、基本用法和注意事项。 比如useState是用来管理状态的,例子可能是一个计数器。useEffect处理副作用,要区分清楚依赖数组的作用,还有清理函数。useContext用于跨组件传递数据,可能需要配合createContext使用。然后还有useReducer,类似于Redux的状态管理,适合复杂状态逻辑。自定义Hooks也很重要,可以封装可复用的逻辑,比如useFetch这样的例子。 然后可能要考虑Hooks的使用规则,比如只在顶层调用,不在循环或条件中使用,还有只在React函数组件或自定义Hook中使用。这些规则用户容易犯错,需要强调。 另外,可能需要提到常见的自定义Hooks案例,比如获取数据、表单处理、定时器这些,让用户知道如何实际应用。还有性能优化相关的Hook,比如useMemo和useCallback,避免不必要的渲染。 需要检查是否有遗漏的重要Hook,比如useRef,用于访问DOM或保存可变值,或者useLayoutEffect和useEffect的区别。还有Hooks的优势,比如代码更简洁,逻辑复用更方便,函数式组件的普及。 用户可能需要实际例子来理解,所以每个部分最好配上简单的代码示例,但根据用户要求,数学公式用LaTeX,但代码可能不需要,不过用户问题里没有提到代码格式,可能正常写就行。不过用户问题主要是笔记介绍,所以结构清晰,分点说明比较重要。 还要注意回答使用中文,避免专业术语翻译问题,比如保持术语正确,比如“副作用”、“状态”等。可能需要检查是否有错误,比如useEffect的依赖数组空的时候相当于componentDidMount,对吗?是的。还有自定义Hook的命名必须以use开头,这是规则之一。 总结下来,回答的结构应该是:简介,常用内置Hooks分点说明,使用规则,自定义Hooks,常见问题或注意事项,优势总结。这样用户能一步步了解Hooks的核心内容,注意事项和实际应用。</think>以下是一份结构清晰的React Hooks核心知识笔记整理: --- ### 一、Hooks 核心概念 1. **作用** 使函数组件拥有类组件的特性(状态管理、生命周期等),**解决类组件的3大痛点**: - 状态逻辑难以复用 - 复杂组件难以理解(尤其是生命周期函数) - `this`指向问题 2. **基本原则** - 只在**函数组件顶层**调用Hook - 只能在**React函数组件**或**自定义Hook**中使用 --- ### 二、常用内置Hooks详解 #### 1. `useState` - 状态管理 ```javascript const [state, setState] = useState(initialValue); ``` - **典型场景**:组件内部状态(如计数器、表单输入) - **注意**:异步更新需用函数形式 `setState(prev => prev + 1)` #### 2. `useEffect` - 副作用处理 ```javascript useEffect(() => { // 副作用操作 return () => { /* 清理函数 */ }; }, [dependencies]); ``` - **依赖项规则**: - 空数组 `[]`:仅在挂载时执行(类似`componentDidMount`) - 不传:每次渲染都执行 - 传值:依赖变化时执行 - **清理机制**:返回函数在组件卸载或下次effect前执行 #### 3. `useContext` - 跨组件传值 ```javascript const value = useContext(MyContext); ``` - 需配合`createContext`使用 - 替代`Context.Consumer`的嵌套写法 #### 4. `useReducer` - 复杂状态管理 ```javascript const [state, dispatch] = useReducer(reducer, initialState); ``` - **适用场景**:多状态关联、复杂更新逻辑 - 可替代`useState`+多状态的情况 --- ### 三、性能优化Hooks #### 1. `useMemo` - 缓存计算结果 ```javascript const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); ``` #### 2. `useCallback` - 缓存函数 ```javascript const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]); ``` --- ### 四、自定义Hook开发 1. **命名规则**:必须以`use`开头(如`useFetch`) 2. **典型场景**: ```javascript // 示例:数据请求Hook function useFetch(url) { const [data, setData] = useState(null); useEffect(() => { fetch(url).then(res => res.json()).then(setData); }, [url]); return data; } ``` --- ### 五、常见问题与注意事项 1. **循环/条件中使用Hook** ❌ 错误示例: ```javascript if (condition) { const [value] = useState(); // 违反Hook调用顺序 } ``` 2. **闭包陷阱** - 在`useEffect`/`useCallback`中访问过时状态时,需通过依赖项或`useRef`解决 --- ### 六、Hooks优势总结 - **逻辑复用**:通过自定义Hook取代HOC/Render Props - **代码简洁**:函数式编程风格,减少模板代码 - **类型友好**:对TypeScript支持更自然 --- 如需深入某个知识点(如具体项目实践案例、原理剖析),可告知具体方向进一步展开说明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值