引言:

Hook 这个单词的意思是"钩子"。React Hooks 是加强版函数组件,提倡组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。React 官方默认提供了一些常用钩子,当然也可以按照需要封装自己的钩子进行使用。

官方钩子:

1.  useState():用于为函数组件引入状态(state),并进行状态数据的读写操作。

语法: const [xxx, setXxx] = React.useState(initValue)

返回值 :  包含2个元素, 第1个(xxx)为内部当前状态值;

第2个(setXxx)为更新状态值的函数,有2种写法::

setXxx(newValue): 参数非函数值, 直接指定新的状态值, 用其覆盖原来的状态值
                        setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值

import React, { useState } from "react";export default function Button() {const [buttonText, setButtonText] = useState("请点击");function handleClick() {return setButtonText("点过了");}return <button onClick = { handleClick } > { buttonText } < /button>;
}

2. useEffect():用于引入副作用操作(控制组件的生命周期)。常见操作:发送ajax异步请求数据、
                         设置订阅 / 启动定时器、手动更改真实DOM。

语法:  useEffect(() => { 
                                 // 在此可以执行任何带副作用操作
                                 return () => { // 组件卸载前做收尾工作, 比如清除定时器/取消订阅等}
                                      }, [stateValue])

useEffect()接受两个参数:第一个参数是一个函数,副作用操作代码放在里面, 如果函数体有return 则相当于 componentWillUnmount();

第二个参数是一个数组传递依赖项,第一次以及当依赖stateValue发生变化时,回调才执行(其他状态变化时不管), 相当于 componentDidUpdate();

第二个参数如果指定的是[ ], 仅第一次 render 后执行, 相当于  componentDidMount()。

第二个参数可以省略,表示全局监测,任何状态变化都会执行useEffect()的回调。

import React, { useState,useEffect} from 'react'export default  function Count(){const [count, setCount] = useState(0)useEffect(()=>{console.log(`useEffect=>点了${count}次`)},[])return (<div><p>点了{count}次</p><button onClick={() => { setCount(count + 1) }} > 请点击 </button></div>)}

3. useCallback():缓存回调函数

语法:useCallback ( fn, dep )

返回一个函数,只有在依赖项发生变化的时候才会更新(返回一个新的函数)。

要知道:函数式组件在每次渲染时,内部函数都会重新定义。场景:很多时候父组件渲染时子组件会跟着渲染即内部函数重新定义,这显然是没有必要的。useCallback可以设置依赖,使得子组件只在依赖发生变化时才进行渲染。

import React, { useState, useCallback } from 'react';export default function App() {const [count1, setCount1] = useState(0);const [count2, setCount2] = useState(0);const handleClick1 = () => {setCount1(count1 + 1)};const handleClick2 = useCallback(() => {setCount2(count2 + 1);}, [count2]);return (<div><p>点了{count1}次</p><button onClick = {handleClick1} > button1 </button><p>点了{count2}次</p><button onClick = {handleClick2} > button2 </button> </div>)
}

上述代码,handleClick2方法使用 useCallback 包装了一层,并且后面还传入了一个 [count2],这里 useCallback 就只会根据 count2 是否发生变化,从而决定是否返回一个新的函数。即使点击 Button1 也不重新渲染 Button2 的内容。

4. useMemo() :缓存函数返回值

语法: useMemo(  fn, dep )

传递一个创建函数 fn 和依赖项 dep,依赖项发生改变的时候,才会重新调用此函数,返回一个新的值缓存起来,避免重复计算,相当于记忆化。

  const [count1, setCount1] = useState(0);const [count2, setCount2] = useState(1);const userInfo1 = {age: count1,name: 'Jerry'
}const userInfo2 = useMemo(() => {return {name: "Tom",age: count2};}, [count2]);return (<div><div>userInfo:{ count1 }</div><div>userInfo:{ count2 }</div></div>) 

小结:useMemo 的场景远比 useCallback 要广泛的很多,我们可以将 useMemo 的返回值定义为返回一个函数这样就可以变通的实现了 useCallback。在开发中当我们有部分变量改变时会影响到多个地方的更新那我们就可以返回一个对象或者数组,通过解构赋值的方式来实现同时对多个数据的缓存。

5. useRef()

(1) 绑定 DOM 节点,模拟类组件的ref

(2) 保存数据,存储跨生命周期渲染的数据。在多组件渲染间共享数据,传入.current生成一个ref对象,让其在组件每个生命周期内都能访问到,useRef 保存的数据变化不会触发 UI 的渲染(区别于 useState )                                    

import React, { useState, useMemo,useRef } from 'react';export default function App() {const inputEl = useRef(null);const onButtonClick = () => {// current 属性指向了真实的 input 这个 DOM 节点,从而可以调用 focus 方法inputEl.current.focus();};return (<><input ref={inputEl} type="text" /><button onClick={onButtonClick}>Focus the input</button></>);
}const [time, setTime] = useState(0);// 定义 timer 容器用于在跨组件渲染之间保存一个变量 const timer = useRef(null);const handleStart = useCallback(() => {// 使用 current 属性设置 ref 的值timer.current = window.setInterval(() => { setTime((time) => time + 1); }, 100);}, []);

6.useContext():定义全局状态

        由于props只能在父给子组件进行通信,如果需要在组件之间共享状态,可以使用useContext()。

语法:

1) 创建Context容器对象:
                    const XxxContext = React.createContext()  
    
                2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
                    <xxxContext.Provider value={数据}>
                        子组件
                    </xxxContext.Provider>
    
                3) 后代组件读取数据:
                      <xxxContext.Consumer>
                       {   value => ( // value就是context中的value数据要显示的内容 ) }
                     </xxxContext.Consumer>

const themes = {light: {foreground: "#000000",background: "#eeeeee"},dark: {foreground: "#ffffff",background: "#222222"}
};
// 创建一个 Theme 的 Contextconst ThemeContext = React.createContext(themes.light);
function App() {// 整个应用使用 ThemeContext.Provider 作为根组件return (// 使用 themes.dark 作为当前 Context <ThemeContext.Provider value={themes.dark}><Toolbar /></ThemeContext.Provider>);
}// 在 Toolbar 组件中使用一个会使用 Theme 的 Button
function Toolbar(props) {return (<div><ThemedButton /></div>);
}// 在 Theme Button 中使用 useContext 来获取当前的主题
function ThemedButton() {const theme = useContext(ThemeContext);return (<button style={{background: theme.background,color: theme.foreground}}>I am styled by theme context!</button>);
}

自定义钩子:

需求1:实现一个监听窗口大小的hook,Resize.js:

import React, { useState, useEffect, useCallback } from "react";// 自定义 hooks函数
function useWinSize() {//初始化状态const [size, setSize] = useState({width: document.documentElement.clientWidth,height: document.documentElement.clientHeight});//设置回调const onResize = useCallback(() => {setSize({width: document.documentElement.clientWidth,height: document.documentElement.clientHeight}, [])})// 副作用useEffect(() => {window.addEventListener('resize', onResize)return () => {window.removeEventListener('resize', onResize)}}, [])return size
}
// 自定义函数式组件
export default function Resize(params) {const size = useWinSize()return (<div> 页面Size: { size.width } * { size.height } </div>)}

需求2:实现一个计时器(自动加1,或手动加一)

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from 'react-dom'function Demo(){//console.log('Demo');const [count,setCount] = React.useState(0)const myRef = React.useRef()React.useEffect(()=>{let timer = setInterval(()=>{setCount(count => count+1 )},1000)return ()=>{clearInterval(timer)}},[])//加的回调function add(){//setCount(count+1) //第一种写法setCount(count => count+1 )}//提示输入的回调function show(){alert(myRef.current.value)}//卸载组件的回调function unmount(){ReactDOM.unmountComponentAtNode(document.getElementById('root'))}return (<div><input type="text" ref={myRef}/><h2>当前求和为:{count}</h2><button onClick={add}>点我+1</button><button onClick={unmount}>卸载组件</button><button onClick={show}>点我提示数据</button></div>)
}export default Demo

常用的hooks入门相关推荐

  1. RabbitMQ常用操作命令和入门案例(一对一的简单模式)

    RabbitMQ常用操作命令和入门案例(一对一的简单模式) 一.RabbitMQ常用操作命令 常见命令列表: # 前台启动Erlang VM和RabbitMQrabbitmq-server # 后台启 ...

  2. React Hooks常用的Hooks钩子函数

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

  3. 总结Linux 的常用命令(Linux入门)

    Linux 这篇文章主要是写一些Linux中常用的命令,属于入门了哈哈(主要是针对Java的学习) 那么首先既然是入门,我们也得知道Linux这玩意到底是咋读的把? 大家可能多多少少也听旁边的人说过很 ...

  4. python常用数据结构_Python入门: 数据结构大汇总

    一.列表 1.列表的创建 列表是有序集合,没有固定大小,能够保存任意数量任意类型的 Python 对象,语法为 [元素1, 元素2, ..., 元素n].关键点是 " 中括号 [ ]&quo ...

  5. Python 常用函数 - Python入门教程

    Python 常用函数 2021 年 3 月 12 日 上午 11:18 [编辑] Python print 函数(一) Python print 函数(二) Python format 函数 Pyt ...

  6. Metasploit进行渗透测试的常用流程【入门】

    Metasploit是一个免费的.可下载的框架,通过它可以很容易地获取.开发并对计算机软件漏洞实施攻击.它具有图形化界面和命令行界面,这里讲的是msfconsole惯用的操作流程.本章使用的metas ...

  7. 一、Hooks入门介绍

    1.什么是Hooks? React Hooks是16.8之后新增一个React特性,它可以让你在函数组件中使用state等其它class组件的特性. 2. 为什么要有Hooks? Class组件: 学 ...

  8. DevExpress_常用控件入门

    简介: XtraEditors   Library是专门为可视化的Studio.NET设计的最优化的一套100%的C#控件 XtraEdiotors Library是一款具有革命性的超过20种数据编辑 ...

  9. Dos批处理常用命令大全入门

    个人也是Dos命令的爱好 当然掌握了dos对一个电脑爱好者也是不会有坏处的.感觉看懂dos后再去接触别的编程更加容易懂了,本人也就是这么过来的. 下面就是一些收集的命令,命令下还有一些解说 pause ...

最新文章

  1. CSDN-markdown编辑器使用手册
  2. Image Processing Wavefronts for HEVC Parallelism
  3. 排序算法之简单插入法排序(Java)
  4. Oracle数据库物理存储结构管理遇到的问题与解决
  5. git add 命令的一个习惯用法:逐个挑选改动
  6. 清除图片下默认的小间隙_PowerMILL软件应用策略(一):模型区域清除策略
  7. php怎么查找函数库,php 查找字符串常用函数说明
  8. C# string byte[] 转换
  9. android studio拟器,十二、安装Android Studio 模拟器
  10. C++写OpenCV图像灰度化
  11. Ionic 安卓兼容性问题解决
  12. HTML5视频方案:支持iPad Safari、Firefox、Chrome、IE9876
  13. 2021年大学生网络安全邀请赛暨第七届上海市大学生网络安全大赛“东华杯”Misc(全)-Writeup
  14. 英语面试技巧以及准备工作
  15. JAVA 实现《拳皇误闯冒险岛》游戏
  16. Acm - 隔壁老王买酒问题
  17. 计算机设备选型原则,计算机中通信技术的选用应遵循什么原则
  18. un4 unreal4 创建路径 曲线 管道 Spline组件 使用方法
  19. U盘中毒后文件夹全部被变成系统隐藏文件,并生成同名文件夹带exe后缀
  20. jmeter安装成功后打不开,提示:Cause: CannotResolveClassException: com.blazemeter.jmeter.threads.concurrency.Conc

热门文章

  1. 仿手环运动app的html,连接手环.html
  2. aⅴgo安装包下载_Mysql 安装
  3. 采集gpu_GPU温度的采集
  4. (转) Dockerfile 中的 COPY 与 ADD 命令 1
  5. Shiro入门视频课程——笔记(一)
  6. 函数式编程了解一下(上)
  7. Juniper CoS 基本配置说明
  8. Android滑动到顶部悬停
  9. SpringAop通知
  10. Win10,Win7,WinServer2012,WinServer2008内存最大支持