1.什么是hook?
2.为什么要用hook?
-: 为函数组件提供状态管理能力, 扩展
-: 在Function组件中勾入更多React 特性, 以use开头
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qcvXgPA7-1669130695588)(micro%20_frontend/img/image-20221122232339894.png)]](https://img.pic99.top/dingtaihe/202404/8489f2e628da488.png)
./components/LikeButton.tsx
// rafc tsrafe
import React, { useState } from 'react'const LikeButton: React.FC = () => {const [like, setLike] = useState(0)const [on, setOn] = useState(true)return ()
}export default LikeButton
改变函数内组件状态,在每次组件更新时候, 记住状态值
纯函数:输入确定, 输出确定,无副作用
副作用:网络请求,手动dom操作,订阅数据来源, … 与纯函数界面渲染不同
两种场景:
实现: 使用useEffect 修改DOM 完成标题更新
class实现:

hooks实现:
// rafc tsrafe
import React, { useEffect, useState } from 'react'const LikeButton: React.FC = () => {const [like, setLike] = useState(0)...useEffect(()=>{//渲染和更新时候执行.document.title = `点击了 ${like} 次`})return (...)
}export default LikeButton
dom操作需要清除监听, 防止内存泄漏,卡顿页面
实现: 使用useEffect 完成鼠标跟踪器(鼠标移动时候显示鼠标位置)
原理:挂载document上, 点击click,修改state,当前值

class实现:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H70K1K3G-1669133553231)(ReactHooks/image-20221122235414537.png)]](https://img.pic99.top/dingtaihe/202404/a55644e47d19eff.png)
hooks实现:// 无依赖时候, 会多次重复调用effect 注册,执行
import React, { useEffect, useState } from 'react'const MouseTracker: React.FC = () => {const [position, setPosition] = useState({ x: 0, y: 0 })useEffect(() => {console.log('add effect',position.x);const updateMouse = (e: MouseEvent) => {console.log('inner');setPosition({x: e.clientX,y: e.clientY})}document.addEventListener('click', updateMouse)return () => {console.log('remove effect',position.x);document.removeEventListener('click', updateMouse)}})console.log('before render',position.x);return (X :{position.x} {` `} Y :{position.y})
}export default MouseTracker
*忘记react声明周期,重新接触react effect,发现每次渲染都会调用effect(有些浪费), 思考如何规避多次调用------>控制effect调用次数
避免每次渲染都会调用,控制次数
实现:控制useEffect的执行
修改前面例子代码 ,利用deps,依赖
function App() {const [show, setShow] = useState(true)return (... {show&& }... );
}export default App;
./components/MouseTracker.tsx
添加依赖项 [], 挂载, 卸载时候执行callback/
避免一更新就执行回调
import React, { useEffect, useState } from 'react'const MouseTracker: React.FC = () => {const [position, setPosition] = useState({ x: 0, y: 0 })useEffect(() => {...document.addEventListener('click', updateMouse)return () => {...}},[])console.log('before render',position.x);return (...)
}export default MouseTracker
./components/LikeButton.tsx
添加
[like]依赖, 只在依赖项,like发生变化时候执行callback
// rafc tsrafe
import React, { useEffect, useState } from 'react'const LikeButton: React.FC = () => {const [like, setLike] = useState(0)...useEffect(()=>{console.log('click')document.title = `点击了 ${like} 次`},[like])return ()
}export default LikeButton
之前方式:hoc / render props
实现: 使用自定义hook 抽象鼠标跟踪器
注:
编写hooks
\hooks\useMousePosition.tsx
import React, { useEffect, useState } from 'react'const useMousePosition= () => {const [position, setPosition] = useState({ x: 0, y: 0 })useEffect(() => {const updateMouse = (e: MouseEvent) => {setPosition({x: e.clientX,y: e.clientY})}document.addEventListener('mousemove', updateMouse)return () => {document.removeEventListener('mousemove', updateMouse)}},[])return position
}export default useMousePosition
调用hooks , 并复用
在需要的地方引入
import React, { useState } from 'react';
...
import useMousePosition from './hooks/useMousePosition';function App() {const [show, setShow] = useState(true)+ const position = useMousePosition()return (+ X :{position.x} {` `} Y :{position.y}
... );
}export default App;

发送请求 (展示Loading, 请求结束隐藏Loading), 实现逻辑复用
hoc: 高阶组件
高阶组件: 是一个函数,接受一个组件作为参数, 返回一个新组件
入参: 组件------>返回:新组件
实现:点击按钮,发送请求, 拿到结果后—>展示图片
/hocs/withLoader.tsx
// high order component
import React from 'react'
import axios from 'axios'interface ILoaderState {data: any,isLoading: boolean
}
interface ILoaderProps {data: any,
}
const withLoader = (WrappedComponent: React.ComponentType
, url: string) => {return class LoaderComponent extends React.Component, ILoaderState> {constructor(props: any) {super(props)this.state = {data: null,isLoading: false}}componentDidMount() {this.setState({isLoading: true,})axios.get(url).then(result => {this.setState({data: result.data,isLoading: false})})}render() {const { data, isLoading } = this.statereturn (<>{ (isLoading || !data) ? data is loading
:...this.props as P} data={data} />}>)}}
}export default withLoader
引入
App.tsx
import React, { useState } from 'react';
...
import withLoader from './hocs/withLoader';import './App.css';interface IShowResult {message:string,status:string,
}const DogShow:React.RC<{data:IShowResult}>=({data})=>{return (<>Dog show:{data.status}
data.message}/>>)
}function App() {const WrappedDogShow = withLoader(DogShow, 'https://dog.ceo/api')return (
logo} className="App-logo" alt="logo" />... ... );
}export default App;
弊端:添加额外空节点, 逻辑 看着复杂