「React 进阶」 React 全部 Hooks 使用大全 (包含 React v18 版本 )

本文深入探讨了React Hooks的背景、愿景和功能,包括useState、useReducer、useContext、useRef等核心Hooks,以及新引入的useSyncExternalStore、useTransition和useDeferredValue。此外,还讲解了自定义Hooks的意义,以及如何使用useDebugValue和useId等工具Hooks。React Hooks已成为主流开发手段,通过它们可以更高效地管理状态和执行副作用,提高代码复用性和工程效率。

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

1.1 技术背景

react hooks 解决了什么问题?

先设想一下,如果没有 Hooks,函数组件能够做的只是接受 Props、渲染 UI ,以及触发父组件传过来的事件。所有的处理逻辑都要在类组件中写,这样会使 class 类组件内部错综复杂,每一个类组件都有一套独特的状态,相互之间不能复用,即便是 React 之前出现过 mixin 等复用方式,但是伴随出 mixin 模式下隐式依赖,代码冲突覆盖等问题,也不能成为 React 的中流砥柱的逻辑复用方案。所以 React 放弃 mixin 这种方式。

类组件是一种面向对象思想的体现,类组件之间的状态会随着功能增强而变得越来越臃肿,代码维护成本也比较高,而且不利于后期 tree shaking。所以有必要做出一套函数组件代替类组件的方案,于是 Hooks 也就理所当然的诞生了。

所以 Hooks 出现本质上原因是:

  • 让函数组件也能做类组件的事,有自己的状态,可以处理一些副作用,能获取 ref ,也能做数据缓存。
  • 解决逻辑复用难的问题。
  • 放弃面向对象编程,拥抱函数式编程。

为什么要使用自定义 Hooks ?

自定义 hooks 是在 React Hooks 基础上的一个拓展,可以根据业务需求制定满足业务需要的组合 hooks ,更注重的是逻辑单元。通过业务场景不同,到底需要React Hooks 做什么,怎么样把一段逻辑封装起来,做到复用,这是自定义 hooks 产生的初衷。

自定义 hooks 也可以说是 React Hooks 聚合产物,其内部有一个或者多个 React Hooks 组成,用于解决一些复杂逻辑。

1.2 技术愿景

目前 hooks 已经成为 React 主流的开发手段,React 生态也日益朝着 hooks 方向发展,比如 React Router, React Redux 等, hooks 也更契合 React 生态库的应用。

随着项目功能模块越来越复杂,一些公共逻辑不能有效的复用,这些逻辑需要和业务代码强关联到一起,这样会让整体工程臃肿,功能不能复用,如果涉及到修改逻辑,那么有可能牵一发动全身。

所以有必要使用自定义 hooks 的方式,hooks 可以把重复的逻辑抽离出去,根据需要创建和业务功能绑定的业务型 hooks ,或者是根据具体功能创建的功能型 hooks 。

1.3 功能概览

在 React 的世界中,不同的 hooks 使命也是不同的,我这里对 React hooks 按照功能分类,分成了 数据更新驱动状态获取与传递,执行副作用,状态派生与保存,和工具类型, 具体功能划分和使用场景如下:

二 hooks 之数据更新驱动

2.1 useState

useState 可以使函数组件像类组件一样拥有 state,函数组件通过 useState 可以让组件重新渲染,更新视图。

useState 基础介绍:

const [ ①state , ②dispatch ] = useState(③initData) 

① state,目的提供给 UI ,作为渲染视图的数据源。

② dispatchAction 改变 state 的函数,可以理解为推动函数组件渲染的渲染函数。

③ initData 有两种情况,第一种情况是非函数,将作为 state 初始化的值。 第二种情况是函数,函数的返回值作为 useState 初始化的值。

useState 基础用法:

const DemoState = (props) => { /* number为此时state读取值 ,setNumber为派发更新的函数 */ let [number, setNumber] = useState(0) /* 0为初始值 */ return (<div> <span>{ number }</span> <button onClick={ ()=> { setNumber(number+1) console.log(number) /* 这里的number是不能够即使改变的*/ } } ></button> </div>)
} 

useState 注意事项:

① 在函数组件一次执行上下文中,state 的值是固定不变的。

function Index(){const [ number, setNumber ] = React.useState(0)const handleClick = () => setInterval(()=>{// 此时 number 一直都是 0setNumber(number + 1 ) },1000)return <button onClick={ handleClick } > 点击 { number }</button>
} 

② 如果两次 dispatchAction 传入相同的 state 值,那么组件就不会更新。

export default function Index(){const [ state, dispatchState ] = useState({ name:'alien' })consthandleClick = ()=>{ // 点击按钮,视图没有更新。state.name = 'Alien'dispatchState(state) // 直接改变 `state`,在内存中指向的地址相同。}return <div> <span> { state.name }</span><button onClick={ handleClick }>changeName++</button></div>
} 

③ 当触发 dispatchAction 在当前执行上下文中获取不到最新的 state, 只有再下一次组件 rerender 中才能获取到。

2.2 useReducer

useReducer 是 react-hooks 提供的能够在无状态组件中运行的类似redux的功能 api 。

useReducer 基础介绍:

const [ ①state , ②dispatch ] = useReducer(③reducer) 

① 更新之后的 state 值。

② 派发更新的 dispatchAction 函数, 本质上和 useState 的 dispatchAction 是一样的。

③ 一个函数 reducer ,我们可以认为它就是一个 redux 中的 reducer , reducer的参数就是常规reducer里面的state和action, 返回改变后的state, 这里有一个需要注意的点就是:如果返回的 state 和之前的 state ,内存指向相同,那么组件将不会更新。

useReducer 基础用法:

const DemoUseReducer = ()=>{/* number为更新后的state值,dispatchNumbner 为当前的派发函数 */ const [ number , dispatchNumbner ] = useReducer((state,action)=>{ const { payload , name} = action /* return的值为新的state */ switch(name){ case 'add': return state + 1 case 'sub': return state - 1  case 'reset': return payload  } return state },0) return <div>当前值:{ number }{ /* 派发更新 */ }<button onClick={()=>dispatchNumbner({ name:'add' })} >增加</button><button onClick={()=>dispatchNumbner({ name:'sub' })} >减少</button><button onClick={()=>dispatchNumbner({ name:'reset' ,payload:666 })} >赋值</button>{ /* 把dispatch 和 state 传递给子组件*/ }<MyChildrendispatch={ dispatchNumbner } State={
  { number }} /> </div>
} 

2.3 useSyncExternalStore

useSyncExternalStore 的诞生并非偶然,和 v18 的更新模式下外部数据的 tearing 有着十分紧密的关联。useSyncExternalStore 能够让 React 组件在 concurrent 模式下安全地有效地读取外接数据源,在组件渲染过程中能够检测到变化,并且在数据源发生变化的时候,能够调度更新。当读取到外部状态发生了变化,会触发一个强制更新,来保证结果的一致性。

useSyncExternalStore 基础介绍:

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值