对React-Hooks的一些理解
自变量与因变量
今天看到一个视频。把react hooks比喻成自变量和因变量,比如:2X = Y
其中的X
就为自变量,Y
为因变量。感觉颇有意思,遂记录一下看完之后的一些感悟。
在常用的几个hooks中,我们可以把他简单地分一下类
自变量
useState
useReducer
useContextTips:
- useReducer可以看做useState的进阶版,利用redux的理念,将多个state合并为一个
- useContext,在一级组件使用createContext来创建context,次级组件中使用useContext来消费一级组件创建的context,以达到更方便地传递自变量
因变量
useMemo
useEffect
useCallback其他(标记变量)
useRef
我们先从useState入手
import {useState} from 'react'
export default function App8() {
const [x, setX] = useState(0)
const y = 2 * x
const changeX = () => {
setX(x+1)
}
return (
<ul onClick={changeX}>
<li>X:{x}</li>
<li>Y: {y}</li>
</ul>
)
}
其中的x就是自变量,自变量的变化导致li视图变化,y是因变量,根据x的变化而变化,最后也导致li视图变化。
现在我们开始利用useMemo和useCallback
import {useState, useCallback, useMemo} from 'react'
export default function Test() {
const [x, setX] = useState(0)
// 指定该y因变量依赖的自变量x
const y = useMemo(() => 2 * x, [x])
// 依赖的自变量依然是x
const changeX = useCallback(() => {
setX(x+1)
}, [x])
return (
<ul onClick={changeX}>
<li>X:{x}</li>
<li>Y: {y}</li>
</ul>
)
}
那么使用Hooks显式的指明因变量,当x
不变的时候,读取缓存好的y
和setX()
,否则每次函数组件执行时,都会重新基于x
render新的y
和setX()
。
组件的功能不仅局限于描述视图,还可以产生副作用
,比如请求数据,操作dom,我们使用useEffect来处理
import {useState, useCallback, useMemo, useEffect} from 'react'
export default function Test() {
const [x, setX] = useState(0)
// 指定该y因变量依赖的自变量x
const y = useMemo(() => 2 * x, [x])
// 依赖的自变量依然是x
const changeX = useCallback(() => {
setX(x+1)
}, [x])
// 依赖的自变量依然是x
useEffect(() => {
// F12打开控制台会发现不仅视图发生变化
// 会发现title也发生变化
document.title = x;
}, [x])
return (
<ul onClick={changeX}>
<li>X:{x}</li>
<li>Y: {y}</li>
</ul>
)
}
可见自变量导致因变量发生变化,因变量不仅可以作用于视图,还能触发副作用。
虽然通过自变量和因变量可以很好地描述视图,但是这个流传太死板了,这时候,使用useRef就可以很好地让这个流程实现个性化
import {useState, useCallback, useMemo, useEffect, useRef} from 'react'
export default function Test() {
const [x, setX] = useState(0)
// 指定该y因变量依赖的自变量x
const y = useMemo(() => 2 * x, [x])
// 依赖的自变量依然是x
const changeX = useCallback(() => {
setX(x+1)
}, [x])
const myRef = useRef(1);
// 判断是否是奇数次更新
const isOdd = myRef.current % 2 !== 0
// 每次更新都会将myRef的值加1
myRef.current++
// 依赖的自变量依然是x
useEffect(() => {
// F12打开控制台会发现不仅视图发生变化
// 会发现title也发生变化
document.title = x;
}, [x])
return (
<ul onClick={changeX}>
{/* 判断是否是奇数次更新,是则显示,否则不显示 */}
{isOdd? <li>X:{x}</li> : null}
<li>Y: {y}</li>
</ul>
)
}
其中useRef就作为标记变量,可以作用在因变量和自变量的不同路径中,增加组件变量的灵活性。