React:Hook
一、为什么要用React Hook
1. 官方介绍
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
2. 组件类的几个缺点
- 大型组件很难拆分和重构,也很难测试
① 业务变得复杂之后,组件之间共享状态变得频繁,此时组件将变得非常难以理解和维护,复用状态逻辑更是难上加难
② 如果使用redux和其中间件, 又将极大的加大项目的复杂度和体积 , 而且需要按照一套严格的标准去写组件和redux,才能保证一定的可维护和可扩展性 - 业务逻辑分散在组件的各个方法之中,导致重复逻辑或关联逻辑
- 组件类引入了复杂的编程模式,比如 render props 和高阶组件
3. 解决方案
- 提出思路
React 团队希望,组件不要变成复杂的容器,最好只是数据流的管道
① 开发者根据需要,组合管道即可
② 组件的最佳写法应该是函数,而不是类
React 早期版本也支持函数组件
① 但是,这种写法有重大限制,必须是纯函数,不能包含状态
② 也不支持生命周期方法,因此无法取代类 - React Hooks 诞生:React Hook 就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件
二、什么是React Hook
1. 什么是React Hook
Hook
钩子React Hooks 含义
① 组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来
② React Hooks 就是那些钩子使用React Hook
① 概念- React 默认提供了一些常用钩子
- 我们也可以封装自己的钩子
- 所有的钩子都是为函数引入外部功能,所以 React 约定,钩子一律使用use前缀命名,便于识别
- 你要使用 xxx 功能,钩子就命名为 usexxx
② 常用钩子
- useState()
- useContext()
- useReducer()
- useEffect()
案例实操
① useState基本使用// 1. 常规写法 // import React from 'react' // // export default class Like001 extends React.Component {// state = {// age: 0 // } // // render() {// return ( // <div> // <h2>我今年{this.state.age}岁了!</h2> // <button onClick={() => this.setState({age: this.state.age + 1})}>按钮</button> // </div> // ); // } // }// 2. hook使用 ——> useState import React, {useState} from 'react'export default () => {// 2.1 使用钩子const [age, setAge] = useState(0);const name = useState('KaiSarH')return (<div><h1>老子是{name}</h1><h2>我今年{age}岁了!</h2><button onClick={() => setAge(age + 1)}>按钮</button></div>) }
② useEffect基本使用
// 1. 常规写法 // import React from 'react' // // export default class Like001 extends React.Component {// state = {// count: 0 // } // // componentDidMount() {// document.title = `点击了${this.state.count}次!` // } // // componentDidUpdate(prevProps, prevState, snapshot) {// document.title = `点击了${this.state.count}次!` // } // // render() {// return ( // <div> // <h2>点击了{this.state.count}次!</h2> // <button onClick={() => this.setState({count: this.state.count + 1})}>增加</button> // </div> // ); // } // }// 2. hook使用 ——> useState、useEffect import React, {useState, useEffect} from 'react'export default () => {const [count, setCount] = useState(0);// useEffect——componentDidMount componentDidUpdate componentWillUnmountuseEffect(() => {document.title = `点击了${count}次`});return (<div><h2>点击了{count}次!</h2><button onClick={() => setCount(count + 1)}>按钮</button></div>) }
③ todo简单案例
④ useEffect第二个参数运用- []相当于生命周期函数的:componentDidMount
- 有第二个参数:相对于生命周期函数:componentDidMount componentDidUpdate
- [count]:只监听count发生改变的时候,才会触发 componentDidUpdate
// // 1. 常规写法 // import React from 'react' // // export default class Like003 extends React.Component {// state = {// count: 0, // name: 'KaiSarH' // } // // componentDidMount() {// document.title = `点击了${this.state.count}次!` // } // // componentDidUpdate(prevProps, prevState, snapshot) {// // document.title = `点击了${this.state.count}次!` // if (prevProps.count !== this.state.count) {// document.title = `点击了${this.state.count}次!` // } // } // // // _dealCountClick() {// this.setState({// count: this.state.count + 1 // }) // } // // _dealNameClick() {// // let name = this.state.name === 'King James' ? 'KaiSarH' : 'King James'; // this.setState({// name: 'King James' // }) // } // // render() {// return ( // <div> // <h2>点击了{this.state.count}次!</h2> // <p>{this.state.name}</p> // <button onClick={() => this._dealCountClick()}>数量</button> // <button onClick={() => this._dealNameClick()}>名字</button> // </div> // ); // } // }// 2. hook使用 ——> useState、useEffect import React, {useEffect, useState} from 'react'export default () => {const [count, setCount] = useState(0);const [name, setName] = useState('KaiSarH');/** 1. 如果不加第二个参数,默认是执行:componentDidMount componentDidUpdate* 2. 加了中括号,默认执行componentDidMount* 3. [状态]:只有状态发生改变时,才能触发componentDidUpdate* */useEffect(() => {console.log('执行了·······')document.title = `点击了${count}次`// return 中返回的相当于在componentWillUnMountreturn {}}, [count])return (<div><h2>姓名:{name}</h2><h2>次数:{count}</h2><button onClick={() => setCount(count + 1)}>加一</button><button onClick={() => setName('King James')}>名称</button></div>) }
- return:相当于componentWillUnmount
// 1. 常规写法 import React, {useState, useEffect} from 'react' import ReactDOM from 'react-dom'const AgeAPI = {age: 0,subscribe(callBack) {this.intervalId = setInterval(() => {console.log('定时器正在执行')this.age += 1;callBack(this.age);}, 1000);},unsubscribe() {clearInterval(this.intervalId);} };// class Like004 extends React.Component {// state = {// age: 0 // } // // componentDidMount() {// AgeAPI.subscribe((age) => {// this.setState({// age // }) // }) // } // // componentWillUnmount() {// AgeAPI.unsubscribe(); // } // // render() {// return ( // <div> // <h2>我是树妖,今年{this.state.age}岁了!</h2> // <button onClick={() => ReactDOM.unmountComponentAtNode(document.getElementById('root'))}>砍树</button> // </div> // ); // } // } // // export default Like004;const Like004 = () => {const [age, setAge] = useState(0);useEffect(() => {AgeAPI.subscribe((currentAge) => {setAge(currentAge)})// 处理副作用代码,相当于在componentWillUnmountreturn () => {AgeAPI.unsubscribe();}}, [])return (<div><h2>我是树妖{age}</h2><button onClick={() => ReactDOM.unmountComponentAtNode(document.getElementById('root'))}>砍树</button></div>) }export default Like004;
⑤ hook中使用网络请求
- 基本使用
import React, {useEffect, useState} from 'react' import ajax from "../http";const Like005 = () => {const [data, setDate] = useState(null);const [loading, setLoading] = useState(true);useEffect(() => {(async () => {const response = await ajax('http://demo.itlike.com/web/xlmc/api/homeApi/categoriesdetail/lk001?itlike=87224866875667849947')setDate(response.data.data);setLoading(false);})()}, [])return (<div>{loading ? <div>正在拼命加载中</div> : data.cate[0].name}</div>) } export default Like005;
- 自己包装一个钩子
import React, {useEffect, useState} from 'react' import ajax from "../http";const useAjax = (url) => {const [data, setDate] = useState(null);const [loading, setLoading] = useState(true);useEffect(() => {(async () => {const response = await ajax(url)setDate(response.data.data);setLoading(false);})()}, [])return {data, loading} } const Like005 = () => {const {data, loading} = useAjax('http://demo.itlike.com/web/xlmc/api/homeApi/categoriesdetail/lk001?itlike=87224866875667849947');return (<div>{loading ? <div>正在拼命加载中</div> : data.cate[0].name}</div>) } export default Like005;
⑥ Hook 使用规则
- 网址
- 只在最顶层使用 Hook
- 只在 React 函数中调用 Hook
⑦ Hook中处理副作用操作
⑧ 性能优化:对比文档前后,如果没有变化就不进行渲染React.PureComponent
import React from 'react' import Other from './other'// export default class Like008 extends React.Component export default class Like008 extends React.PureComponent{state = {age: 0};/*componentDidMount() {setInterval(()=>{this.setState({// age: this.state.age + 1age: 100})}, 1000);}*/componentDidMount() {setInterval(()=>{this.setState({age: this.state.age + 1})}, 1000);}render() {console.log('render被调用了~~~~');return (<div><Other otherName="撩课学院"/>{this.state.age}</div>)} }
React.memo
import React from 'react'const Other = ({otherName})=>{console.log('other组件中的render被调用了');return (<h3>我叫: {otherName}</h3>) };// export default Other export default React.memo(Other);
⑨ useCallback使用
示例
const memoizedCallback = useCallback(() => {doSomething(a, b);},[a, b], );
实操
① 第二个参数决定了是否允许第一个参数执行
② 二个参数发生变化则允许执行,否则则不允许执行
③ 第一个参数第一次会执行一次,之后才会判断第二个参数是否发生变化然后再执行/*useCallback网址: https://zh-hans.reactjs.org/docs/hooks-reference.html#usecallbackconst memoizedCallback = useCallback(() => {doSomething(a, b);},[a, b], ); - 第二个参数b决定了是否允许第一个参数执行 - 第一个参数第一次会执行, 之后会根据第二个参数的变化决定是否执行 */ import React, {useState, useCallback} from 'react'const Like009 = ()=>{const [age, setAge] = useState(1);const [weight, setWeight] = useState(50);function clickHandler() {setAge(age + 1);}return (<div><p>年龄: {age} 岁</p><button onClick={clickHandler}>年龄+1</button><p>体重: {weight}千克</p>{/*<button onClick={()=>{setWeight(weight + 1)}}>体重+1</button>*/}<button onClick={useCallback(()=> setWeight(weight + 1), [age])}>体重+1</button></div>) };export default Like009;
⑩ usereducer
[网址](https://zh-hans.reactjs.org/docs/hooks-reference.html#usereducer)
import React, {useState, useReducer} from 'react'const initialState = {count: 0 };function reducer(state, action) {switch (action.type) {case "increment":return {count: state.count + 1};case "decrement":return {count: state.count - 1}} }function Counter() {const [state, dispatch] = useReducer(reducer, initialState);return (<div>计算结果: {state.count}<button onClick={()=>dispatch({type: 'increment'})}>+</button><button onClick={()=>dispatch({type: 'decrement'})}>-</button></div>) }export default Counter;
⑪ usecontext
import React, {useContext} from 'react'const themes = {dark: {width: 100,height: 40,borderRadius: 10,border: 'none',color: 'green',backgroundColor: 'orange'} };const ThemeContext = React.createContext();function App() {return (<ThemeContext.Provider value={themes.dark}><ToolBar /></ThemeContext.Provider>) }function ToolBar() {return (<div><ThemedButton /></div>) }function ThemedButton() {const theme = useContext(ThemeContext);console.log(theme);return (<button style={theme}>点我一下</button>) }export default App;
React:Hook相关推荐
- React全Hook项目实战在线聊天室历程(三):加个音乐直播?
前情提要: React全Hook项目实战在线聊天室历程(一):基本功能 React全Hook项目实战在线聊天室历程(二):引用与话题功能 正文 聊天应该有什么?背景音乐,茶与酒,零食,后两个我是没法实 ...
- linux钩子函数和回调函数,Linux Kernel 学习笔记10:hook函数
(本章基于: Linux -4.4.0-37) linux 内核中有一套hook函数机制,可在不同hook点位置监控网络数据包,并执行丢弃.修改等操作.网络防火墙就是通过此机制实现的. 注册注销hoo ...
- 读书笔记《React:引领未来的用户界面开发框架》
<React:引领未来的用户界面开发框架>(GitHub 附demo版) 1.Component的创建与复合 1.1 React简介 背景介绍,全书概览 1.本质上是一个状态机,它以精简的 ...
- React:开发者工具谷歌插件下载安装
React:开发者工具谷歌插件 最近学习前端react主要是想大概浏览一下,这里提供尚硅谷的是视屏资料中的谷歌插件的下载. (如有侵权联系删除) 这里提供我的下载地址,其中除了插件,还有一起案例源码, ...
- React:Component组件
组件允许开发者将复杂的UI页面拆分为独立可复用的代码片段,并对每个代码片段进行独立构思.React中的组件,在概念上类似于JavaScript函数,它接收任意的入参(对应当该组件的props属性),返 ...
- react:hash_亲爱的React:感谢信
react:hash by Alex Vervloet 由Alex Vervloet 亲爱的React:感谢信 (Dear React: A thank you letter) Dear React, ...
- React:input输入框只能输入英文和特殊字符(可以自定义限制)
React:input输入框只能输入英文和特殊字符(可以自定义限制) 直接上代码: antd3.x版本 render(){return (<Form.Item>{getFieldDecor ...
- react性能监控根据工具_高性能React:3个新工具可加快您的应用程序
react性能监控根据工具 by Ben Edelstein 通过本·爱德斯坦 高性能React:3个新工具可加快您的应用程序 (High Performance React: 3 New Tools ...
- 开源精选:AntdFront —— React 纯 Hook 多标签微前端管理系统解决方案
AntdFront 项目动机 使用 React 开发管理系统前端, 选择 Ant Design of React(antd)做 UI 十分常见,然而与其相关的开源项目普遍存在以下问题: 大多使用 an ...
- react引入多个图片_重新引入React:v16之后的每个React更新都已揭开神秘面纱。
react引入多个图片 In this article (and accompanying book), unlike any you may have come across before, I w ...
最新文章
- 多次Jquery引发head.insertBefore( script, head.firstChild );
- java 抽象工厂工厂_java之抽象工厂
- 编程理论:多态,继承,和开闭原则
- SAP UI5的support Assistant
- 基于VHDL自动售邮票机设计
- 电脑4次连续故障音_格力空调电子膨胀阀故障判定与“E6”处理方法
- 基于java百货中心供应链管理系统(含源文件)
- linux pivot root,[mydocker]---通过例子理解chroot 和 pivot_root
- c++实验6—项目一
- 语音信号预处理1——chirp信号的生成与接收
- 常用的13个开源GIS软件,值得收藏!
- 数据结构与算法 哈希表的特点
- Android多媒体相关框架
- webrtc QOS方法一(NACK实现)
- Struts2详细执行流程自己总结
- 北京3月去哪玩 赏花踏青登山六大推荐
- MC官方模板的分析Day1
- oracle修改分区表的默认空间,Oracle数据库学习_Oracle分区表的分区占用空间为什么是8M?如何修改分区的初始空间?...
- 收藏本站——添加到浏览器收藏夹
- 天梵古法健康知识普及:足阳明胃经经穴
热门文章
- 56.Linux/Unix 系统编程手册(下) -- SOCKET 介绍
- 2.nginx 配置
- 17. Contoller(2)
- 百度地图API常规应用十功能
- Mysql存储过程中使用cursor
- [2019杭电多校第四场][hdu6621]K-th Closest Distance(主席树)
- 微星msi B450M+i5-8500+1060成功黑苹果
- Noip前的大抱佛脚----文章索引
- c++11 实现半同步半异步线程池
- jxl读数据库数据生成xls 并下载