react学习(五) ---- hooks
文章目录
- 1. 函数和类组件的缺陷
- 1.1 函数式组件缺陷
- 1.2 类组件缺陷
- 1.3 类组件和函数式组件和Hooks的对比
- 2. Hooks
- 2.1 useState🌟
- 2.2 useEffect🌟
- 2.3 useSelector和useDispatch
- 2.4 特殊场景使用的Hooks
- 2.4.1 useContext
- 2.4.2 useReducer(了解,用的少)
- 2.4.3 useCallback和useMemo
- 2.4.4 useRef --- 获取dom
- 2.5 自定义Hooks
react-router部分直接看官方文档。 react-router
1. 函数和类组件的缺陷
1.1 函数式组件缺陷
1.2 类组件缺陷
1.3 类组件和函数式组件和Hooks的对比
2. Hooks
2.1 useState🌟
使用规则:
当执行完setXXX
后,使用useState
定义的变量会消失,State API
重新创建新变量保留下来,当页面重新渲染时,获取得到的该变量值就是State API
所保留的值。
2.2 useEffect🌟
- 基本使用;
- 清除effect;
- 使用多个effect;
- 性能优化;
组件首次渲染或数据更新完后执行useEffcet()
,所有的副作用全部放在其中。
需要清除的Effcet
:
6. eventbus
7. store
的subscribe
因为组件的首次渲染和数据更新后重新渲染都会重新执行useEffect()
,所以需要在每次dom更新前和组件卸载时清除监听,useEffect()
的返回值可以帮助我们来做这件事。
另外,Effect可以使用多个,进行逻辑分离,之后学习了自定义Hook可以抽离出来进行复用。
组件某一个地方的数据改变就会触发组件更新,那么就会执行所有的effect(可能其他地方数据并不需要更新),这样可能浪费性能(网络请求,订阅和取消订阅)
2.3 useSelector和useDispatch
性能优化:
当页面中有多个组件,并且都使用了state
中的数据,那么其中一个组件修改了state
中的数据,其他组件也会重新渲染;
但是如果我们在使用useSelector
时使用shallowEqual
对新旧state
进行比较,那么react
将根据浅层比较的结果决定是否重新渲染。
2.4 特殊场景使用的Hooks
2.4.1 useContext
首先在顶层提供相应的context,之后使用useContext进行调用。
2.4.2 useReducer(了解,用的少)
2.4.3 useCallback和useMemo
我们在组件中定义各种各样的回调函数,在每次组件更新时函数都会被再次创建,但是之前创建的函数还存在吗?有被销毁吗?
没有的。我们可以通过使用useCallback()
和memo()
进行优化。
useCallBack()
— 优化回调函数
const increment = useCallback(() => {props.increment()}, [props])
useMemo
— 优化返回值
两者的区别:
2.4.4 useRef — 获取dom
import { useRef } from "react"export default function HomeRanking(props) {const titleRef = useRef()return (<div><h1 ref={titleRef}>排行榜</h1></div>)
}
2.5 自定义Hooks
当多个组件有相同的逻辑时就可以将其抽取出来,你可以选择使用高阶组件,当然也可以尝试使用自定义Hooks
。
注❗️:自定义hooks
必须要以use
开头(react官方规定)。
import { useContext } from 'react'
import { TokenContext, UserContext } from '../context'export const useUserToken = () => {const user = useContext(UserContext)const token = useContext(TokenContext)return [user, token]
}
另外,当组件内有渲染之外的副作用(
https://yuanbao.tencent.com/bot/app/share/chat/bN6cE6zvgeyQ)时,也可以选择将该部分抽离出来,放在useEffect
中(例:监听窗口滚动位置)
import { useEffect, useState } from "react"export const useScrollPosition = () => {const [scrollX, setScrollX] = useState(0)const [scrollY, setScrollY] = useState(0)useEffect(() => {const handleScroll = () => {setScrollX(window.scrollX)setScrollY(window.scrollY)}// 监听window.addEventListener('scroll', handleScroll)return () => {// 清除监听window.removeEventListener('scroll', handleScroll)}}, [])return [scrollX, scrollY]
}