自定义Hook useUpdate

本文介绍如何在React中仅让useEffect在状态变量n第二次更新时触发,通过使用自定义Hook实现更精确的副作用控制。

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

useEffect 如何在第二次才更新n

有问题的写法

//更新
 //想在n更新的时候去更新
        //[]里面写了什么,那就是那个东西变了就去执行
        //注意:还没有点+1 ,控制台显示n变了是因为n从undefined 变成0了 

	useEffect(() => { 
	          console.log('n变了')
	        }, [n])
        

在这里插入图片描述
怎样在真正点击后才变化时才显示n变了?

思路

  • 使用自定义Hook ,用一个state来记录n变化的次数,
  • 判断一下,从第二次开始显示n变了

方法一:

代码如下


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

//第一个组件
const App = (props) => {

    const [m, setM] = useState(0);
    const [n, setN] = useState(0);
    const onClickN = () => {
      setN(n + 1);
    };
    const onClickM = () => { 
      setM(m + 1);
    }

    //写在App内
            //写一个state用来记n变了几次,默认0次
            const [nUpdateCount, setNUpdateCount] = useState(0);
            //需要每次n变化的时候把count加1
            //写useEffect 更新,给count+1
            useEffect(()=>{ 
              // setNUpdateCount(nUpdateCount+1) //这样写会有一个警告
              setNUpdateCount(x=> x+1)
            },[n])
             
             //加一个判断,如果count>1才显示n变了
            useEffect(() => { 
              if(nUpdateCount >1){  
                  console.log('n变了') 
                }
             },[nUpdateCount])


  return (
    <div>
      {n}
      <button onClick={ onClickN }>
        +1
      </button>
      <hr />
      {m}
      <button onClick={ onClickM }>
        +1
      </button>
      <hr/>
    </div>
  )
};



export default App;

方法二:自定义Hook useUpdate

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

  //解决useEffect 在n没真正变化的时候显示n变了 
    //方法二:自定义Hook
    //写在App组件外
    const useUpdate = (fn,array) =>{
      const [count, setCount] = useState(0);
      useEffect(() => {
        setCount( x => x+1);
      },[...array]);
      
      useEffect(()=>{
        if(count > 1){
          fn();
        }
      },[count]);
    };
//第一个组件
const App = (props) => {

    const [m, setM] = useState(0);
    const [n, setN] = useState(0);
    const onClickN = () => {
      setN(n + 1);
    };
    const onClickM = () => { 
      setM(m + 1);
    }
    
    //和useEffect一样的使用
    
    useUpdate(() =>{
      console.log("n变了");
    },[n])


	return (
	   <div>
	      {n}
	      <button onClick={ onClickN }>
	        +1
	      </button>
	      <hr />
	      {m}
	      <button onClick={ onClickM }>
	        +1
	      </button>
	      <hr/>
	    </div>
	  )
	};

export default App;

在这里插入图片描述

<think>我们正在讨论如何在React中创建和使用自定义Hook。根据引用内容,我们可以总结出以下步骤: 1. **定义自定义Hook**:创建一个以`use`开头的函数(这是React的约定,以便识别为Hook)。 2. **在自定义Hook中使用内置Hook**:在自定义Hook函数内部,可以使用`useState`、`useEffect`等内置Hook,也可以使用其他自定义Hook。 3. **返回需要暴露的值或函数**:自定义Hook可以返回任何需要的内容,比如状态、函数等。 4. **在组件中使用自定义Hook**:在函数组件中调用自定义Hook,获取其返回的值或函数,并在组件中使用。 引用[3]中明确提到创建自定义Hook的步骤: - 定义一个以"use"开头的函数。 - 在自定义Hook中使用内置Hook(如useState, useEffect等)或其他自定义Hook。 - 在组件中使用这个自定义Hook。 引用[4]提供了一个具体的例子:创建`useModal`自定义Hook,它管理一个模态框的可见状态,并返回切换可见状态的函数和当前可见状态。 下面我们将按照这些步骤详细说明。</think>### 如何在 React 中创建和使用自定义 Hook #### 一、自定义 Hook 的基本概念 自定义 Hook 是 React 16.8 引入的函数式编程特性,它允许开发者**提取可复用的状态逻辑**,实现"关注点分离"。与普通函数不同,自定义 Hook 可以调用 React 内置 Hook(如 `useState`, `useEffect`),并遵循特定命名约定[^2]。 #### 二、创建自定义 Hook 的步骤 1. **命名规范** 函数名必须以 `use` 开头(例如 `useToggle`),这是 React 识别 Hook 的强制规则[^3]。 2. **定义逻辑** 在函数体内使用内置 Hook 构建功能: ```javascript // useCounter.js import { useState } from 'react'; const useCounter = (initialValue = 0) => { const [count, setCount] = useState(initialValue); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); return { count, increment, decrement }; // 返回状态和方法 }; ``` 3. **状态封装** 可包含多个状态和副作用: ```javascript // useWindowSize.js import { useState, useEffect } from 'react'; const useWindowSize = () => { const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight }); useEffect(() => { const handleResize = () => { setSize({ width: window.innerWidth, height: window.innerHeight }); }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); // 空依赖数组确保只运行一次 return size; }; ``` #### 三、使用自定义 Hook 在组件中直接调用,如同内置 Hook: ```javascript // CounterComponent.jsx import useCounter from './useCounter'; const Counter = () => { const { count, increment } = useCounter(5); // 初始化值为5 return ( <div> <p>当前计数: {count}</p> <button onClick={increment}>增加</button> </div> ); }; ``` #### 四、最佳实践 1. **单一职责原则** 每个 Hook 只解决一个特定问题(如 `useForm` 处理表单状态,`useFetch` 管理数据请求)[^1]。 2. **依赖管理** 在 `useEffect` 中正确处理依赖数组,避免无限循环。 3. **组合复用** 自定义 Hook 可以嵌套使用: ```javascript const useUserData = () => { const { data } = useFetch('/api/user'); const isOnline = useNetworkStatus(); return { user: data, isOnline }; }; ``` #### 五、实际应用案例 模态框控制(引用示例扩展)[^4]: ```javascript // useModal.js import { useState, useCallback } from 'react'; const useModal = () => { const [isOpen, setIsOpen] = useState(false); const open = useCallback(() => setIsOpen(true), []); const close = useCallback(() => setIsOpen(false), []); const toggle = useCallback(() => setIsOpen(prev => !prev), []); return { isOpen, open, close, toggle }; }; // 组件中使用 const ModalComponent = () => { const { isOpen, open, close } = useModal(); return ( <> <button onClick={open}>打开模态框</button> {isOpen && ( <div className="modal"> <button onClick={close}>关闭</button> </div> )} </> ); }; ``` > **关键优势**: > - 逻辑复用:避免在多个组件中重复相同状态管理代码 > - 代码组织:将复杂组件拆分为更小的函数单元 > - 测试友好:可独立测试 Hook 逻辑而不依赖 UI
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值