React Hooks的作用是对函数型组件进⾏增强,让函数型组件可以存储状态, 可以拥有处理副作⽤的能⼒,可以在不使⽤类组件的情况下, 实现相同的功能。

useState实现原理

useState方法接收参数,可以是普通值,也可以接收函数做为参数,如果是函数做为参数,组件初始化时会调用函数,返回的结果就时初始状态值;useState方法调用返回数组,数组参数为状态值跟改变状态值的方法;useState使用闭包的方式存储状态,能多次调用,因此需要外部声明数组变量存储状态值跟方法,并添加索引;当调用更改状态方法时重新渲染

let state = [];
let setters = [];
let stateIndex = 0;function createSetter (index) {return function (newState) {state[index] = newState;render ();}
}function useState (initialState) {state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;setters.push(createSetter(stateIndex));let value = state[stateIndex];let setter = setters[stateIndex];stateIndex++;return [value, setter];
}function render () {stateIndex = 0;effectIndex = 0;ReactDOM.render(<App />, document.getElementById('root'));
}

useEffect实现原理

useEffect是实现类组件当中生命周期函数的钩子。useEffect执行时机,传入空数组([]),组件初始化执行一次,同类组件componentDidMount;不传第二个参数时,组件初始化执行,组件更新也会执行,同类组件componentDidMount,componentDidUpdate;当useEffect传入的函数返回一个函数时,返回的函数执行时机会在组件卸载之后执行,同类组件的componentWillUnmount生命周期。当useEffect的第二个参数传入参数时,值发生变化,函数也会执行。useEffect同样也能多次调用。代码实现:

// 上一次的依赖值
let prevDepsAry = [];
let effectIndex = 0;function useEffect(callback, depsAry) {// 判断callback是不是函数if (Object.prototype.toString.call(callback) !== '[object Function]') throw new Error('useEffect函数的第一个参数必须是函数');// 判断depsAry有没有被传递if (typeof depsAry === 'undefined') {// 没有传递callback();} else {// 判断depsAry是不是数组if (Object.prototype.toString.call(depsAry) !== '[object Array]') throw new Error('useEffect函数的第二个参数必须是数组');// 获取上一次的状态值let prevDeps = prevDepsAry[effectIndex];// 将当前的依赖值和上一次的依赖值做对比 如果有变化 调用callbacklet hasChanged = prevDeps ? depsAry.every((dep, index) => dep === prevDeps[index]) === false : true;// 判断值是否有变化if (hasChanged) {callback();}// 同步依赖值prevDepsAry[effectIndex] = depsAry;effectIndex++;}
}

useReducer实现原理

useReducer接收两个参数,第一个是reducer函数,第二个为初始状态值。useReducer调用返回数组,数组第一个值是状态值,第二个是dispatch方法。
代码实现:

function useReducer (reducer, initialState) {const [state, setState] = useState(initialState);function dispatch (action) {const newState = reducer(state, action);setState(newState);}return [state, dispatch];
}

上面是一些常用钩子的实现原理,下面是组件其他拓展钩子的使用方法

useContext

useContext在跨组件层级获取数据时简化获取数据的代码,实现跨组件间的通信;
通过creactContext方法调用返回的对象中的Provider包裹需要传值的组件,后辈组件通过useContext钩子调用creactContext方法返回的对象,获取到传递的值;
没有useContext之前需要通过creactContext方法返回对象的Consumer获取。

import { creactContext, useContext } from 'react'
const countContext = creactContext();
function App() {return <countContext.Provider value={100}><Foo /></countContext.Provider>
}
funtion Foo() {const count = useContext(countContext)return <div>{count}</div>
}

不使用useContext获取

import { creactContext, useContext } from 'react'
const countContext = creactContext();
function App() {return <countContext.Provider value={100}><Foo /></countContext.Provider>
}
funtion Foo() {return <countContext.Consumer>{(count)=> <div>{count}</div>}</countContext.Consumer>
}

useMemo

useMemo 的⾏为类似Vue中的计算属性, 可以监测某个值的变化, 根据变化值计算新值;useMemo 会缓存计算结果. 如果监测值没有发⽣变化, 即使组件重新渲染, 也不会重新计算. 此⾏为可以有助于避免在每个渲染上进⾏昂贵的计算

import { useMemo } from 'react'const result = useMemo(() => {// 如果count值发生变化函数重新执行return result
}, [count])

memo方法和useCallback

memo跟useCallback都属于优化组件性能的方法,memo 类似类组件中的 PureComponent 和 shouldComponentUpdate,如果组件中的数据没有发⽣变化, 阻⽌组件更新;useCallback的作用缓存函数, 使组件重新渲染时得到相同的函数实例
下面案例通过useCallback缓存setCount方法,子组件在触发事件时,通过memo调用后就不会重新渲染;如果不执行useCallback直接将setCount传给子组件,子组件虽然调用了memo方法,但是会在重新渲染时认为传入的值发生了变化,所以会重新渲染,useCallback就完美规避的这个问题

import React, { useCallback, setCount } from 'react'function Counter() {const [count, setCount] = useState(0);const resetCount = useCallback(() => setCount(0), [setCount]);return <div><span>{count}</span><button onClick={() => setCount(count + 1)}>+1</button><Test resetCount={resetCount} /></div>
}
//Test
import { memo } from 'react'function Test (props) => {console.log('Test re-render');return <div><button onClick={props.resetCount}>reset</button></div>
}
export default memo(Test)

useRef

useRef可以获取DOM元素对象,同时还可以保存数据,即使组件重新渲染, 保存的数据仍然还在,保存的数据被更改不会触发组件重新渲染;useRef调用返回一个对象,存储的数据存放在对象的current属性中

import React, { useRef } from 'react'function App() {const username = useRef();const handler = () => console.log(username); //{ current: input }return <input ref={username} onChange={handler} />
}

自定义Hook

⾃定义 Hook 是标准的封装和共享逻辑的⽅式;⾃定义 Hook 是⼀个函数, 其名称以 use 开头;⾃定义 Hook 其实就是逻辑和内置 Hook 的组合

function useUpdateInput (value) {const [value, setValue] = useState(value)return {value,onChange: event => setValue(event.target.value)}
}function App(){const usernameInput = useUpdateInput('');const passwordInput = useUpdateInput('');const submitForm = event => {event.preventDefault();console.log(usernameInput.value);console.log(passwordInput.value);}return <form onSubmit={submitForm}><input type="text" name="username" {...usernameInput }/><input type="password" name="password" {...usernameInput }/><input type="submit"/></form>
}

React 路由 Hooks

react-router-dom 路由提供了4个钩⼦函数,用于获取路由信息

文章为个人学习笔记记录心得,有错误欢迎指正

React Hooks常用的Hooks钩子函数相关推荐

  1. React Hooks(钩子函数)

    React Hooks 什么是Hooks? UseState() useReducer() useContext() useEffect() useRef() 自定义钩子函数 React Hooks中 ...

  2. react-10 函数式写法rsc,配合HOOKS钩子函数

    性能优化:useMemo :用于组件性能优化(缓存计算属性,变化才执行)是通过缓存值的方式实现性能优化 (计算缓存):适用于复杂的计算场景,如复杂的列表渲染,对象深拷贝... //   //   // ...

  3. 知识梳理---------Hooks钩子函数的使用

    1 React Hooks介绍 1.1 React Hooks是用来做什么的 对函数型组件进行增强,让函数型组件可以存储状态,一个拥有处理副作用的能力. 组件中只要不是把数据转换成视图的代码,就是属于 ...

  4. React 生命周期、Hooks

    React React 生命周期 Hooks Hook 的特点 Effect Hook 自定义 hooks React 生命周期 react 生命周期是组件实例从创建运行到销毁的一系列过程 compo ...

  5. [react] 请描述下你对react的新特性Hooks的理解?它有哪些应用场景?

    [react] 请描述下你对react的新特性Hooks的理解?它有哪些应用场景? 在 React 中使用 class 继承 React.Component,就可以在类里面使用各种各样的钩子函数,比如 ...

  6. react dispatch_React系列自定义Hooks很简单

    React系列-Mixin.HOC.Render Props(上) React系列-轻松学会Hooks(中) React系列-自定义Hooks很简单(下) 我们在第二篇文章中介绍了一些常用的hooks ...

  7. 拯救react的hooks:react的问题和hooks的作用

    react组件和react组件逻辑复用 react是一个视图层组件方案,最核心的功能就是绑定视图与数据和逻辑,实现响应式的渲染.react的组件最核心的就是渲染出的Vdom,也就是jsx的部分. 渲染 ...

  8. 使用react实现select_使用 Hooks 优化 React 组件

    奇技指南 本文内容主要是我之前分享的文字版,若想看重点的话可以看之前的Slide: https://ppt.baomitu.com/d/75fc979a 本文作者奇舞团前端开发工程师李喆明. 需求描述 ...

  9. React之 常见的hooks

    前面是类组件,今天是函数式组件 函数式组件的特点 没有状态 没有生命周期 没有this useState src>index.js import React from 'react' impor ...

最新文章

  1. 暑期集训4:栈,树,优先队列 例 :  UVA - 514 ​​​​​​​​​​​​​​
  2. ipython中matplotlib无法显示图片Could not connect to any x display
  3. Nginx10m+高并发内核优化详解
  4. Zabbix监控Linux主机设置
  5. Shell(11)——awk(1)
  6. POJ - 3254 Corn Fields(状压dp)
  7. 全面拥抱HDR时机已到?
  8. 计算机本地连接怎么找不到了,网络,本地连接不见了解决办法
  9. 终于在2000年的联想6920上较完美的运行起了Gentoo Linux
  10. html中设置负边距的意义,css负边距之详解
  11. nohup xxx 后台进程关闭,可以这样避免
  12. Ubuntu 16.04 卸载vmware
  13. 钉钉免登陆前端操作详解
  14. Virtual DOM 详解
  15. 弹琴、cosplay、打羽毛球……现在的机器人都是戏精丨世界机器人大会
  16. android 壁纸改变回调,android_launcher的源码详细分析和壁纸修改
  17. Python计算中国GDP在那一年超越美国GDP(假设)
  18. ActiveMQ 之安全认证
  19. mysql 标识列是什么,mysql中标识列是什么意思有什么用
  20. 记腾讯互娱网站布局(2)

热门文章

  1. 基于javaweb的在线奶茶店系统(java+jsp+javascript+servlet+mysql)
  2. html5扑克牌游戏源码,【web】纯JavaScript实现window经典纸牌游戏
  3. VS2017开发activex
  4. boss直聘账号异常登不上_【苹果IOS游戏账号分享】别再留言它了,二哈已经立马给你们买了!不一样的真地下城游戏,奶好全队才是你该做的事——地下城与治疗者...
  5. CentOS服务器清除用户登录记录和命令历史方法
  6. week11 day7 模型层
  7. 缓解人才饥荒,中国南京大学成立国内首个人工智能学院
  8. docker卸载及安装
  9. [简单]poi 设置word 2007段落与表格底纹
  10. jquery使用replaceWith替换元素,但是替换的位置不对应的问题