React Hooks常用钩子及基本原理解读

 更新时间:2023年10月26日 09:04:14   作者:绿足  
这篇文章主要介绍了React Hooks常用钩子及基本原理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一. 简述

在以往的react16.8前, 我们React组件创建方式基本包含两种方式: 类组件, 纯函数组件

React 团队希望组件最佳写法应该是函数,而不是类。

然而常规的纯函数组件有以下特点:

  • 没有状态
  • 没有生命周期
  • 没有 this

因存在如上特点,使得纯函数组件只能做UI展示的功能, 涉及到状态的管理与切换就不得不用到类组件或这redux。

但因为简单的页面也是用类组件,同时要继承一个React实例,使得代码会显得很重。

‘Hooks’ 单词意思为:钩子。

React Hooks 意思是:组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码“钩”进来。

React Hooks常用钩子有如下四种:

  • useState()
  • useContext()
  • useReducer()
  • useEffect()

使用hooks 我们会发现没有了继承,渲染逻辑,生命周期等, 代码看起来更加的轻便简洁了。

React 约定,钩子一律使用 use 前缀命名 (自定义钩子都命名为:useXXXX)

二. 常用举例及原理分析

useState 状态钩子

官方示例:

import React, {useState} from 'react'
const AddCount = () => {
  const [ count, setCount ] = useState(0)
  const addcount = () => {
    let newCount = count
    setCount(newCount+=1)
  } 
  return (
    <>
      <p>{count}</p>
      <button onClick={addcount}>count++</button>
    </>
  )
}

原理:

// 我们实现一个简易版的useState
let memoizedStates = [ ]  // 多个useState 时需要使用数组来存
let index = 0
function useState (initialState) {
   memoizedStates[index] = memoizedStates[index] || initialState
   let currentIndex = index;
   function setState (newState) {
      memoizedStates[currentIndex] = newState
      render()
   }
   return [memoizedStates[index++], setState]
}

useContext 共享状态钩子

该钩子的作用是,在组件之间共享状态。

可以解决react逐层通过Porps传递数据。

import React,{ useContext } from 'react'
const ShareContext= () => {
  const AppContext = React.createContext({})
  const A =() => {
    const { name } = useContext(AppContext)
    return (
        <p>我是A组件的名字{name}<span>我是A的子组件{name}</span></p>
    )
}
const B =() => {
  const { name } = useContext(AppContext)
  return (
      <p>我是B组件的名字{name}</p>
  )
}
  return (
    <AppContext.Provider value={{name: 'hook测试'}}>
    <A/>
    <B/>
    </AppContext.Provider>
  )
}
export default ShareContext

useContext(context) 是针对 context (上下文) 提出的api。

它接受React.createContext()的返回结果作为参数(也就是context对象并返回最近的context)。

使用useContext将不再需要Provider 和 Consumer。

当最近的context更新时,那么使用该context的hook将会重新渲染。

useReducer(): Action 钩子

React本身不提供状态管理。

而useReducer() 提供了状态管理。

其基本原理是通过用户在页面中发起action, 从而通过reducer方法来改变state, 从而实现页面和状态的通信。

import React,{useReducer} from 'react'

const MyReducer= () => {
const reducer = (state, action) =>  {
 if(action.type === ''add){
  return {
  ...state,
  count: state.count +1,
  }
 }else {
   return state
  }
 }
const addcount = () => { 
  dispatch({
    type: 'add'
  })
 }
const [state, dispatch] = useReducer(reducer, {count: 0})
return (
<>
<p>{state.count}</p>
<button onClick={addcount}>count++</button>
</>
)
}
export default MyReducer

使用useReducer() 代替了Redux的功能, 但useReducer 无法提供中间件等功能。

useEffect(): 副作用钩子

React常规开发中,我们习惯将一些处理副作用的操作,如:异步请求等 放在特定的生命周期中。

useEffect 则是为函数组件提供了副作用的钩子。

useEffect() : 接收两个参数, 第一个是进行的异步操作, 第二个是数组,用来给出Effect的依赖项。

第二个参数(数组)发生变化, ==useEffect()==就会执行。

第二项不填时, useEffect() 会在每次组件渲染时执行。

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

const AsyncPage = ({name}) => {
const [loading, setLoading] = useState(true)
const [person, setPerson] = useState({})
//  useEffect 类似compomnetDidMount 初始化会执行,更新时会执行
  useEffect(() => {
    setLoading(true)
    setTimeout(()=> {
      setLoading(false)
      setPerson({name})
    },3000)
  },[name])
  return (
    <div>
      {loading?<p>Loading...</p>:<p>{person.name}</p>}
    <div/>
  )
}

const PersonPage = () =>{
  const [state, setState] = useState('')
  const changeName = (name) => {
    setState(name)
  }
  return (
    <>
      <AsyncPage name={state}/>
      <button onClick={() => {changeName('名字1')}}>名字1</button>
      <button onClick={() => {changeName('名字2')}}>名字2</button>
    </>
  )
}

export default PersonPage 

创建自己的Hooks

有时候我们需要创建自己想要的Hooks, 来满足更便捷的开发。

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

const usePerson = (name) => {
const [loading, setLoading] = useState(true)
const [person, setPerson] = useState({})

  useEffect(() => {
    setLoading(true)
    setTimeout(()=> {
      setLoading(false)
      setPerson({name})
    },2000)
  },[name])
  return [loading,person]
}

const AsyncPage = ({name}) => {
  const [loading, person] = usePerson(name)
    return (
      <div>
        {loading?<p>Loading...</p>:<p>{person.name}</p>}
      </div>
    )
  }

const PersonPage = () =>{
  const [state, setState]=useState('')
  const changeName = (name) => {
    setState(name)
  }
  return (
    <div>
      <AsyncPage name={state} />
      <button onClick={() => {changeName('名字1')}}>名字1</button>
      <button onClick={() => {changeName('名字2')}}>名字2</button>
    </div>
  )
}

export default PersonPage 

上面自定义了一个Hooks, 它接受一个字符串, 返回一个数组, 数组中的两个状态在使用usePerson() 时, 会根据传入的不同反而返回不同的状态。

React Hooks 概要及未来

根据官方文档的说法:

完全可选

  • 100%向后兼容 (Hook 不会含任何破坏性改动)
  • 现在可用 (Hook 已发布于 v16.8.0)
  • 没有计划从React中移除class
  • Hook不会影响对React概念的理解 (Hook 为React提供了相关API:props, state,context, refs以及生命周期)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • React替换传统拷贝方法的Immutable使用

    React替换传统拷贝方法的Immutable使用

    Immutable.js出自Facebook,是最流行的不可变数据结构的实现之一。它实现了完全的持久化数据结构,使用结构共享。所有的更新操作都会返回新的值,但是在内部结构是共享的,来减少内存占用
    2023-02-02
  • React 组件中的state和setState()你知道多少

    React 组件中的state和setState()你知道多少

    这篇文章主要为大家详细介绍了React组件中的state和setState(),文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • react ant design样式覆盖问题

    react ant design样式覆盖问题

    这篇文章主要介绍了react ant design样式覆盖问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Remix路由模块输出对象loader函数详解

    Remix路由模块输出对象loader函数详解

    这篇文章主要为大家介绍了Remix路由模块输出对象loader函数详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2023-04-04
  • React如何实现全屏监听Esc键

    React如何实现全屏监听Esc键

    这篇文章主要介绍了React如何实现全屏监听Esc键,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • React UI组件库之快速实现antd的按需引入和自定义主题

    React UI组件库之快速实现antd的按需引入和自定义主题

    react入门学习告一段路,下面这篇文章主要给大家介绍了关于React UI组件库之快速实现antd的按需引入和自定义主题的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • React 父子组件通信的实现方法

    React 父子组件通信的实现方法

    这篇文章主要介绍了React 父子组件通信的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • useReducer使用详解及其应用场景

    useReducer使用详解及其应用场景

    这篇文章主要介绍了useReducer使用详解及其应用场景,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • React中的Props类型校验和默认值详解

    React中的Props类型校验和默认值详解

    这篇文章主要为大家详细介绍了React中的Props类型校验和默认值,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • React Hooks - useContetx和useReducer的使用实例详解

    React Hooks - useContetx和useReducer的使用实例详解

    这篇文章主要介绍了React Hooks - useContetx和useReducer的基本使用,本文通过实例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11

最新评论