七、React Hooks

143 阅读3分钟

Hook

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

useState(保存组件状态)

  const [count, setCount] = useState(0);

useEffect(处理副作用)和useLayoutEffect (同步执行副作用)

Function Component 不存在生命周期,所以不要把 Class Component 的生命周期概念搬过来试图对号入座。

useEffect(() => {
    第一次加载时执行,依赖里的数据更新时执行
  return () => {
    页面销毁时执行 return 的函数
  }
}, [依赖的数据;空数组,表示不依赖])

useEffect和useLayoutEffect有什么区别?

简单来说就是调用时机不同, useLayoutEffect 和原来 componentDidMount & componentDidUpdate 一致,在 react完成DOM更新后马上同步调用的代码,会阻塞页面渲染。而 useEffect 是会在整个页面渲染完才会调用的 代码。

官方建议优先使用 useEffect

useCallback(记忆函数)

  • useCallback返回的是里面的整个个函数
    • 当依赖的值发生变化,useCallback才会重新声明一次,
    • 不变化就会从缓存中拿上一次值———防止没有值变化时,组件重新渲染,方法重新创建
    • 第二个参数[] 存放依赖的值
var handleClick = useCallback(
    ()=>{ 
        console.log(name) 
    },[name]) 
    
<button onClick={()=>handleClick()}>hello</button>
 //只有name改变后, 这个函数才会重新声明一次, 
 //如果传入空数组, 那么就是第一次创建后就被缓存, 如果name后期改变了,拿到的还是老的name。 
 //如果不传第二个参数,每次都会重新声明一次,拿到的就是最新的name.

useMemo 记忆组件

  • useMemo返回的是计算出来的结果,
    • 只有依赖值改变的时候才会重新计算,
    • 不改变就会拿上次缓存的结果——防止计算繁琐占有资源
    • 第二个参数[] 存放依赖的值 useCallback 的功能完全可以由 useMemo 所取代,如果你想通过使用 useMemo 返回一个记忆函数也是完全可以的
useMemo(() => fn, [])

唯一的区别是:useCallback 不会执行第一个参数函数,而是将它返回给你,而 useMemo 会执行第一个函数并 且将函数执行结果返回给你。

useRef(保存引用值)

  • 两个作用
  1. 绑定 dom/组件 上获得 dom/组件 对象
  2. 保存临时变量,不然其消失
const count = useRef(null);

useContext

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的 value。由上层组件中距离当前组件最近的 <GlobalContext.Provider> 的 value prop 决定。

let GlobalContext = React.createContext();

export default function Father() {
  return (
    <GlobalContext.Provider value={{myname:'admin'}} >
       <Child></Child>
    </GlobalContext.Provider>
  )
}


 function Child() {
     const value = useContext(GlobalContext)
  return (
    <div>Child---{value.myname}</div>
  )
}

别忘记 useContext 的参数必须是 context 对象本身

  • 正确:  useContext(MyContext)
  • 错误:  useContext(MyContext.Consumer)
  • 错误:  useContext(MyContext.Provider)

useReducer

  const [state, dispatch] = useReducer(reducer, initialState);
  1. useState的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
  2. 在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。
function reducer(prestate, action) {
  switch (action.type) {
    case 'add':
      return {count: prestate.count + 1};
    case 'sub':
      return {count: prestate.count - 1};
    default:
      return prestate
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {count: 0});
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'sub'})}>-</button>
      <button onClick={() => dispatch({type: 'add'})}>+</button>
    </>
  );
}

自定义hook

当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。而组件和 Hook 都是函数,所以也同样适用这种方式。

自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。