前言
Hook 是 React 16.8 的新增特性。它是完全可选的,并且100%向后兼容。它可以让你使用函数组件的方式,运用类组件以及 react 其他的一些特性,比如管理状态、生命周期钩子等。从概念上讲,React 组件一直更像是函数。而 Hook 则拥抱了函数,同时也没有牺牲 React 的精神原则。
优点:
1、代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护。 2、组件树层级变浅。 3、不用再去考虑 this 的指向问题。
缺点:
对一些钩子函数不支持。当下 v16.8 的版本中,还无法实现 getSnapshotBeforeUpdate 和 componentDidCatch 这两个在类组件中的生命周期函数。
Hook 规则
不在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。 不在普通的 JavaScript 函数中调用 Hook,在 React 的函数组件或者自定义 Hook 中调用 Hook。
Hook API
useState 在函数组件中维护自己的状态
useEffect 在函数组件中实现生命周期钩子函数
useContext 用来处理多层级传递数据的方式,减少组件嵌套
useReducer 跟react-redux的使用方式一样,算是提供一个 mini 的 Redux 版本
useCallback 获得一个记忆函数,避免在某些情况下重新渲染子组件,用来做性能优化
useMemo 获得一个记忆组件,和useCallback非常类似,它适用于返回确定的值
useRef 生成对 DOM 对象的引用,它是一个真正的引用,而不是把值拷过去
useImperativeHandle 透传ref,用于让父组件获取子组件内的引用
useLayoutEffect 同步执行副作用,在页面完全渲染完成后,操作DOM
useState
在类组件中,我们使用 this.state来保存组件状态,并对其修改触发组件重新渲染。而在函数组件中,由于没有 this 这个黑魔法,可能通过 useState 来帮我们保存组件的状态。
import { useState, useEffect, useContext } from 'react';
export default () => {
// state状态管理
const [count, setCount] = useState(0)
return <div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>点击增加</button>
<button onClick={()=>setCount(count-1)}>点击增加</button>
</div>
}
useEffect
语法:useEffect(fn,Array)
第一个参数传递函数,可以用来做一些副作用比如异步请求,修改外部参数等行为。 第二个参数是个数组,数组中的值发生变化才会触发 useEffect 第一个参数中的函数。 如果第二个参数是个空数组的话,默认会在页面加载后执行一次。 如果第一个参数有返回值,会在组件销毁或者调用函数前调用。 可以使用useEffect模拟componentDidMount、 componentDidMount 和 componentWillUnmount钩子函数。
import React, { useState, useEffect } from "react";
function App(){
const [count, setCount] = useState(0);
useEffect(()=>{
//只要count有变化,就会执行这里
},[count])
useEffect(()=>{
//如果在下面没有参数的话,页面加载后执行,执行一次
return()=>{
//页面退出的时候执行
}
},[])
}
useContext
用来处理多层级传递数据的方式,使用 useContext 可以解决 Consumer 多状态嵌套的问题
import React, { useContext } from "react";
const colorContext = React.createContext("gray");
function Bar() {
const color = useContext(colorContext);
return <div>{color}</div>;
}
function Foo() {
return <Bar />;
}
function App() {
return (
<colorContext.Provider value={"red"}>
<Foo />
</colorContext.Provider>
);
}
|