react自定义Hook 写法、规则(只能在组件/自定义Hook内调用)

React 自定义 Hook(Custom Hook)本质上是:把组件中可复用的状态逻辑抽出来 。你做过 React,应该见过 useState、useEffect,自定义 Hook 就是在这些基础上封装逻辑。


1. 自定义 Hook 写法

命名必须以 use 开头:

javascript 复制代码
import { useState } from 'react'

function useCount(initialValue = 0) {
  const [count, setCount] = useState(initialValue)

  const increment = () => {
    setCount(count + 1)
  }

  const decrement = () => {
    setCount(count - 1)
  }

  return {
    count,
    increment,
    decrement
  }
}

export default useCount

使用:

javascript 复制代码
import useCount from './hooks/useCount'

function App() {
  const { count, increment } = useCount(10)

  return (
    <>
      <div>{count}</div>

      <button onClick={increment}>
        +
      </button>
    </>
  )
}

结果:

复制代码
点击按钮
↓
count变化
↓
组件重新渲染

类似把业务逻辑抽出去。


2. React Hook 两条核心规则(必须记)

官方规则可概括成:

规则1:只能在 React 函数组件里调用

✅ 正确:

javascript 复制代码
function User() {
    const [name] = useState('Tom')

    return <div>{name}</div>
}

❌ 错误:

普通函数:

scss 复制代码
function getData() {
    const [name] = useState('Tom')
}

报错:

r 复制代码
Invalid hook call

规则2:只能在自定义 Hook 中调用 Hook

✅ 正确:

csharp 复制代码
function useUser() {
    const [user] = useState(null)

    return user
}

因为:

bash 复制代码
自定义Hook
↓
内部可以继续调用 useState/useEffect

总结成一句:

Hook 只能在:

  • React 函数组件
  • 自定义 Hook(useXXX)

里面调用。


3. Hook 不能写在条件里

这是很多人踩坑。

错误:

javascript 复制代码
function Demo({ show }) {

    if (show) {
        const [count] = useState(0)
    }

    return <div>demo</div>
}

原因:

React 要保证:

makefile 复制代码
第一次渲染:
useState
useEffect

第二次渲染:
useState
useEffect

调用顺序必须一致。

条件会变成:

makefile 复制代码
第一次:
useState

第二次:
无

React 不知道状态对应谁。


正确:

javascript 复制代码
function Demo({ show }) {

    const [count] = useState(0)

    if (show) {
        console.log(count)
    }

    return <div></div>
}

4. Hook 不能写循环

错误:

scss 复制代码
for(let i=0;i<5;i++){
    useState()
}

错误:

scss 复制代码
list.map(() => {
   useEffect()
})

都会破坏调用顺序。


5. Hook 不能写嵌套函数

错误:

scss 复制代码
function App() {

   function handleClick() {
       useState()
   }

}

因为点击时才执行。


6. 自定义 Hook 常见封装

封装请求

以前组件:

scss 复制代码
useEffect(()=>{
   fetchUser()
},[])

抽:

scss 复制代码
function useUser() {
    const [user,setUser] = useState(null)

    useEffect(()=>{
        api.getUser()
          .then(res=>setUser(res))
    },[])

    return user
}

组件:

javascript 复制代码
function App() {
    const user = useUser()

    return <div>{user?.name}</div>
}

类似 Vue Composition API:

scss 复制代码
useUser()

封装窗口监听

javascript 复制代码
function useWindowSize() {

    const [size,setSize] =
        useState(window.innerWidth)

    useEffect(()=>{

        const resize = ()=>{
            setSize(window.innerWidth)
        }

        window.addEventListener(
            'resize',
            resize
        )

        return ()=>{
            window.removeEventListener(
                'resize',
                resize
            )
        }

    },[])

    return size
}

使用:

scss 复制代码
const width = useWindowSize()

7. React 为什么限制 Hook 只能顶层调用?

因为 React 内部靠调用顺序保存状态:

第一次:

scss 复制代码
1 -> useState(count)
2 -> useEffect()
3 -> useState(name)

第二次必须还是:

scss 复制代码
1 -> useState(count)
2 -> useEffect()
3 -> useState(name)

顺序变了:

复制代码
count
name
effect

状态就乱了。

所以才有:

复制代码
不能条件调用
不能循环调用
不能嵌套调用

8. 面试常问总结(建议背)

什么是自定义 Hook?

把组件内可复用的状态逻辑抽离成函数,以 use 开头,可复用 state、副作用、事件等逻辑。

Hook 使用规则?

  1. 只能在函数组件调用
  2. 只能在自定义 Hook 调用
  3. 不能写条件
  4. 不能写循环
  5. 不能写嵌套函数
  6. 必须顶层调用

为什么?

React 依赖 Hook 调用顺序保存状态,顺序变化会导致状态错乱。

这类问题在 React 中高级岗位很常见。

相关推荐
用户461169657283 小时前
网站 HTTPS 不稳定?证书排查指南
前端
n87653 小时前
Playwright Java WEB UI 自动化实现框架与逻辑
java·前端·ui
keyipatience3 小时前
TypeScript学习(1)
前端·javascript·学习·typescript·html·css3
xifangge20254 小时前
基于 JavaScript 实现 CNC 数控切削参数与螺纹公差纯前端核算引擎
开发语言·前端·javascript
wangruofeng4 小时前
2026 Web 技术选型指南,AI 时代如何选择适合项目的技术栈
前端·aigc·ai编程
honkun64 小时前
vue 表格组件 vxe-table 修改滚动条样式,修改滚动条样式,统一宽度、颜色与自动隐藏
前端·javascript·vue.js
爱勇宝4 小时前
研究数字孪生的这半年,做了个 Demo,也有了一些新想法
前端·程序员
不可能片场5 小时前
工程实践 一个缓存把选片从十分钟压到一分钟
前端·electron
前端小万5 小时前
探索副业五个月,最终以放弃告终
前端·后端·面试
FRing035 小时前
JavaScript入门到精通二十四(正则表达式、元字符、修饰符)
开发语言·前端·javascript·正则表达式