Hooks
React hook Hook是一个特殊的函数,是React 16.8的新增特性。他可以让你在不编写class的情况下使用state以及其他的React 特性
Hook中没有this,React是通过Hook的调用顺序来对应相应的Hook,所以Hook需要在组件的最顶层使用
Hook中每一次渲染都会捕获定义他们的那次渲染中的props和state,可以说Hook的每次渲染其实都生成了一套当前的独立的state和props
总结:hooks是一种在纯函数的基础上演变而来的新函数,区别于纯函数有自己的状态,而相比于class非常简洁, 没有生命周期的架构束缚。
目录
useState
const [state, setState] = useState(initVal); 返回一个 state,以及更新 state 的函数。
setSatete函数用于更新 state。它接收一个新的 state 值并将组件的一次重新渲染加入队列。
useState的参数一般是作为state的初始值而言,可以是数字,字符串,数组,对象,或者函数。若为函数只在定义的时候执行一次。
useState & setState:
useState 是直接替换是state内容,而setState是合并内容。
对比于两种写法:
在异步条件下则不同
当我设置为异步更新,点击按钮延迟到3s之后去调用setCount函数,当我快速点击按钮时,也就是说在3s多次去触发更新,但是只有一次生效,因为 count 的值是没有变化的。
当使用函数式更新 state 的时候,这种问题就没有了,因为它可以获取之前的 state 值,也就是代码中的 prevCount 每次都是最新的值。
useEffect
useEffect会在每次 DOM 渲染后执行,不会阻塞页面渲染。它同时具备componentDidMount、componentDidUpdate和componentWillUnMount三个生命周期函数的执行时机。
1)当useEffect的返回值是一个函数的时候,react在下一次执行useEffect之前先执行一遍清理工作,整个组件的生命流程如下:
组件挂载-> 执行副作用 -> 组件更新 -> 执行清理函数 -> 执行副作用 -> 组件更新 -> 执行清理函数 -> 组件被卸载
2) 第二个参数可以是空数组,也可以是多个值,一般将useEffect所用到的props和state都传进去
当参数传[], 只在挂载和卸载的时候,执行,相当于是didMount和wiillUnMount的结合
useCallback & useMemo
解决问题:当父组件的state发生改变是,为避免子组件不必要的渲染, 类似 shouldComponentDidUpdate钩子,起到的作用就是根据当前的条件判断当前的渲染是否执行
useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。
useMemo
效果是: 只有在count的值变化的时候,才会去执行expensive昂贵的计算,避免不必要的浪费和消耗。
useCallback: 类似于useMemo,useCallBack返回的是函数而非变量
使用场景: 有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。
根据useCallBack的第二个参数,依附在callback身上,达到根据父组件的条件去控制是否重新渲染子组件,提高了性能。
总结: useCallback 和 useMemo 参数相同,第一个参数是函数,第二个参数是依赖项的数组。主要区别是 React.useMemo 将调用 fn 函数并返回其结果,而 React.useCallback 将返回 fn 函数而不调用它。
useReducer
在hooks中提供了的useReducer 功能, useReducer 接受一个reducer函数作为参数,reducer接受两个参数一个是state另一个是action。然后返回一个状态count和dispath, count是返回状态中的值, 而dispatch 是一个可以发布事件来更新state的。
对于围绕state的数据修改操作的统一化管理。
useRef
- useRef是一个方法,且useRef返回一个可变的ref对象
- initialValue被赋值给其返回值的.current对象
- ref对象与自建一个{current:‘’}对象的区别是:useRef会在每次渲染时返回同一个ref对象,即返回的ref对象在组件的整个生命周期内保持不变。自建对象每次渲染时都建立一个新的。
- 本质上,useRef就是一个其.current属性保存着一个可变值“盒子”。
import React,{ useReducer,useRef } from 'react'
export default function ShoppingList() {
const inputRef = useRef();
const [items, dispatch] = useReducer((state,action)=> {
switch(action.type){
case 'add':
return [...state,
{
id:state.length,
name:action.name
}]
case 'remove':
return state.filter((_,index) => index != action.index)
case 'clear':
return [];
default:
return state;
}
},[])
function handleSubmit(event){
event.preventDefault();
dispatch({
type:'add',
name:inputRef.current.value
});
inputRef.current.value = '';
}
return (
<>
<form onSubmit={handleSubmit}>
<input ref={inputRef}/>
</form>
<button
className="button is-danger"
onClick={
() => dispatch({type:'clear'})
}>clear</button>
<ul>
{items.map((item,index) => (
<li className="section" key={item.id}>{item.name}
<button className="button" onClick={
() => dispatch({type:'remove',index})
}>X</button>
</li>
))}
</ul>
</>
)
}
Example 充当全局变量: