About Hooks
Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则:
- 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
- 只能在React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。
useState
1. 形式
import React,{useState} from 'React'
let [num,setNum]=useState(0)
useState接收一个参数作为初始值,返回一个数组。
- 数组第一项是状态值
- 数组第二项是改变状态值的函数
2. 使用方法
<button onClick={()=>{setNum(n+1)}}>+1</button>
3. 多项状态值使用useState注意事项
let [a,setA] = useState(0)
let [b,setB] = useState('B')
let [c,setC] = useState(1)
- 没有声明key,那么如何将useState和每个状态值对应起来呢?
- React是根据多个useState的声明顺序来确定useState对应的状态值的。换句话说,在进行调用useState()API时,一定不能使用判断语句等可能改变其顺序的逻辑,否则会报错。
- 对象类型不支持局部更新
如果state是一个对象,setState不会帮助我们局部更新state。正确的方式是setState({...state, n: 1}) - setState接受函数
setState(i=>i+1)
useEffect
1. 形式
useEffect(() => {
doSomething
},[]);
参数
- 第一个参数接收一个函数,在对应的生命周期执行。
- 第二个参数接受一个数组,当数组中的状态值发生变化时调用 useEffect 。
- 返回值:返回一个函数,React 将会在执行清除操作时调用它。
2. 原理说明
useEffect 在第一次渲染之后 和 每次更新之后都会执行(在渲染之前执行可以使用useLayoutEffect)。你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载 mount”还是“更新 update”。
3. 对比class
//挂载(第一次渲染
componentDidMount => useEffect(()=>{...},[])
//更新
componentDidUpdate => useEffect(()=>{...},[props])
//清理
componentWillUnmount => useEffect(()=>{ return()=>{ console.log('cleanUp') } })
useMemo、useCallback、React.memo
参考:https://juejin.cn/post/684490...
使用方法:
const App = () => {
const handleClick = useCallback(()=> console.log('click'),[]) //防止每次memo对比时,props(杉树声明)都发生了浅层改变导致的多余渲染
let user = useMemo(()=>({ name: 'oliver' }),[]) //防止每次memo对比时,props(对象字面量)都发生了浅层改变导致的多余渲染
return (
<Child onClick={handleClick} user={user} />
)
}
const Child = React.memo((props)=>{
return (
<button onClick={props.handleClick}>child</button>
)
})
额外说明:
useMemo(()=>fn,[...depds])
//等价于
useCallbacl(fn,[...depds])
总结:
不要盲目使用这些hooks进行性能优化
- 在子组件不需要父组件的值和函数的情况下,只需要使用memo函数包裹子组件即可。
- 在使用函数的情况,需要考虑有没有函数传递给子组件使用useCallback。
- 在值有所依赖的项,并且是对象和数组等值的时候而使用useMemo(当返回的是原始数据类型如字符串、数字、布尔值,就不要使用useMemo了)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。