useState
const [state,setState] = useState(initState);
返回 state 以及更新 state 的函数。setState 传入一个值用于更新 state,且 setState 不会在后面的渲染中变化,也就是说 setState 的地址是不会变的。
如果需要旧的 state 计算出新的 state,可以将函数传递给 setState,这个函数会接收到之前的 state,且返回一个更新后的值。如下:
setState((preState) => preState + 1);
useState 中的 setState 不会自动合并更新对象(class 组件中的 setState 会合并更新),如果需要合并更新对象,可以用展开运算符实现。返回的是展开了 preState 和 updateState 的对象。如下:
setState((preState) => ({...preState,...updateState}));
惰性初始 state,传入的参数只会在组件的初始渲染中起作用,后面的渲染都会忽略。如果传入是函数(返回一个值的函数),这个函数只会在初始渲染的时候被调用。
const [state,setState] = useState(() => {
const initialState = returnState(props);
return initialState;
})
如果调用了 state 的更新函数(setState),且传入的是当前的 state,React 将跳过子组件的渲染以及 effect 函数的执行(采用的是Object.is(…) 比较方法,与 “===” 几乎相同,不相同的是 Object.is(…) 判断 NaN 等于 NaN 是true,判断 +0 和 -0 是false)。
###### useEffect 这个 Hook 接收一个函数,函数是在组件渲染到屏幕后执行的,相当于一些生命周期(compnentDidUpdate这种组件render之后执行的生命周期)。
防止内存泄漏,清除 Effect 也是很必要的,所以每次执行 Effect,都需要返回一个清除它的函数。且这个函数会在组件卸载的时候执行,所以执行下一个 effect 的时候,上一个 effect 已经被清除了。
Effect 会在浏览器布局和绘制之后延迟调用,且它会在任何新的渲染前执行。
Effect 的第二个参数是订阅参数,如果传入这个参数,只有在它变化的时候,Effect 会创建新的订阅,而不是组件更新就需要创建新的订阅。
useCallBack
const callBack = useCallback(() => doAnything(),[state]);
返回一个回调函数,这个回调函数不会随着渲染而改变(引用不变),只有第二个参数变化时,这个函数才会更新,成为一个新的回调函数。
useMemo
const value = useMemo(() => computed(a,b),[a,b]);
相当于计算属性,返回的 value 这个值,它仅会在 [a,b] 改变之后重新计算,减少开销。
- 传入 useMemo 的函数会在渲染期间执行。此时 DOM 树并未完全建立,所以不能在里面进行 DOM 操作,如适合在 useEffect 中的操作在 useMemo 中则不一定适用。
- 如果没有传入第二个参数,则每次渲染都会重新计算新的值。
useRef
Ref 是访问 DOM 的主要方式,很常用的一种场景就是让输入框聚焦,例:
function FocusComponent(){
const inputElemet = useRef(null);
const buttonClick = () => inputElement.current.focus();
return <>
<input ref={inputElemet} type='text' />
<button onClick={buttonClick}>点击输入框聚焦</button>
</>
}
- 相比于 ref ,useRef 中的 DOM 元素是可变的,如果把 ref 传给一个元素,ref 就只会指向这个元素,而useRef 是可变的。
- useRef 变化时,并不会有提示,且变更返回的 inputElemet 的 current 属性不会引起组件重新渲染。如果想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现。