React Hooks常用的Hooks钩子函数
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钩子函数相关推荐
- React Hooks(钩子函数)
React Hooks 什么是Hooks? UseState() useReducer() useContext() useEffect() useRef() 自定义钩子函数 React Hooks中 ...
- react-10 函数式写法rsc,配合HOOKS钩子函数
性能优化:useMemo :用于组件性能优化(缓存计算属性,变化才执行)是通过缓存值的方式实现性能优化 (计算缓存):适用于复杂的计算场景,如复杂的列表渲染,对象深拷贝... // // // ...
- 知识梳理---------Hooks钩子函数的使用
1 React Hooks介绍 1.1 React Hooks是用来做什么的 对函数型组件进行增强,让函数型组件可以存储状态,一个拥有处理副作用的能力. 组件中只要不是把数据转换成视图的代码,就是属于 ...
- React 生命周期、Hooks
React React 生命周期 Hooks Hook 的特点 Effect Hook 自定义 hooks React 生命周期 react 生命周期是组件实例从创建运行到销毁的一系列过程 compo ...
- [react] 请描述下你对react的新特性Hooks的理解?它有哪些应用场景?
[react] 请描述下你对react的新特性Hooks的理解?它有哪些应用场景? 在 React 中使用 class 继承 React.Component,就可以在类里面使用各种各样的钩子函数,比如 ...
- react dispatch_React系列自定义Hooks很简单
React系列-Mixin.HOC.Render Props(上) React系列-轻松学会Hooks(中) React系列-自定义Hooks很简单(下) 我们在第二篇文章中介绍了一些常用的hooks ...
- 拯救react的hooks:react的问题和hooks的作用
react组件和react组件逻辑复用 react是一个视图层组件方案,最核心的功能就是绑定视图与数据和逻辑,实现响应式的渲染.react的组件最核心的就是渲染出的Vdom,也就是jsx的部分. 渲染 ...
- 使用react实现select_使用 Hooks 优化 React 组件
奇技指南 本文内容主要是我之前分享的文字版,若想看重点的话可以看之前的Slide: https://ppt.baomitu.com/d/75fc979a 本文作者奇舞团前端开发工程师李喆明. 需求描述 ...
- React之 常见的hooks
前面是类组件,今天是函数式组件 函数式组件的特点 没有状态 没有生命周期 没有this useState src>index.js import React from 'react' impor ...
最新文章
- 暑期集训4:栈,树,优先队列 例 : UVA - 514 ​​​​​​​​​​​​​​
- ipython中matplotlib无法显示图片Could not connect to any x display
- Nginx10m+高并发内核优化详解
- Zabbix监控Linux主机设置
- Shell(11)——awk(1)
- POJ - 3254 Corn Fields(状压dp)
- 全面拥抱HDR时机已到?
- 计算机本地连接怎么找不到了,网络,本地连接不见了解决办法
- 终于在2000年的联想6920上较完美的运行起了Gentoo Linux
- html中设置负边距的意义,css负边距之详解
- nohup xxx 后台进程关闭,可以这样避免
- Ubuntu 16.04 卸载vmware
- 钉钉免登陆前端操作详解
- Virtual DOM 详解
- 弹琴、cosplay、打羽毛球……现在的机器人都是戏精丨世界机器人大会
- android 壁纸改变回调,android_launcher的源码详细分析和壁纸修改
- Python计算中国GDP在那一年超越美国GDP(假设)
- ActiveMQ 之安全认证
- mysql 标识列是什么,mysql中标识列是什么意思有什么用
- 记腾讯互娱网站布局(2)
热门文章
- 基于javaweb的在线奶茶店系统(java+jsp+javascript+servlet+mysql)
- html5扑克牌游戏源码,【web】纯JavaScript实现window经典纸牌游戏
- VS2017开发activex
- boss直聘账号异常登不上_【苹果IOS游戏账号分享】别再留言它了,二哈已经立马给你们买了!不一样的真地下城游戏,奶好全队才是你该做的事——地下城与治疗者...
- CentOS服务器清除用户登录记录和命令历史方法
- week11 day7 模型层
- 缓解人才饥荒,中国南京大学成立国内首个人工智能学院
- docker卸载及安装
- [简单]poi 设置word 2007段落与表格底纹
- jquery使用replaceWith替换元素,但是替换的位置不对应的问题