React 之 Hook

140 阅读2分钟

React 之 Hook

什么是 Hook?

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性(如 函数式组件)

Hook 是一些可以让你在 函数组件“钩入” React state 及生命周期等特性的函数Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。

Hook 使用规则

Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件中调用 Hook,不要在其他 JavaScript 函数中调用。(还能在自定义的 Hook 中调用 Hook)。

State Hook

useState 会返回一对值:当前状态 和一个让你 更新它的函数

import React, { useState } from 'react';

function Example() {
  // 声明一个新的叫做 “count” 的 state 变量
  const [count, setCount] = useState(0);
  const [todo, setTodo] = useState({dosomething: "aaa"});

  return (
    <div>
      <p>You clicked {count} times</p>
      <p>You clicked {todo.dosomething} times</p>
      <button onClick={() => {
          setCount(count + 1);
          setTodo({dosomething: "bbb"})
      }}>
        Click me
      </button>
    </div>
  );
}

Effect Hook

useEffect 就是一个 Effect Hook,,给函数组件增加了操作副作用的能力 (副作用函数) 。它跟 class 组件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount 具有相同的用途,只不过被合并成了一个 API。

例如,下面这个组件在 React 更新 DOM 后会设置一个页面标题:

import React, { useState, useEffect } from 'react';

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

  // 相当于 componentDidMount 和 componentDidUpdate: 
  // 组件初始渲染及数据更新导致的渲染都会调用 useEffect 内部事件
  useEffect(() => {
    // 使用浏览器的 API 更新页面标题
    document.title = `You clicked ${count} times`;
    
    alert("update"); // 每次更新count都会执行
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

副作用函数还可以通过返回一个函数,来指定如何“清除”副作用(防止引起内存泄露):

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}