[React Hooks 翻譯] 2-8 初探Hooks

Hooks有不少種,好比react

State Hook

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

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

這個例子上一篇有提到過,這裏useState就是一個Hook(待會會討論什麼是Hook)。咱們在函數內部調用這個Hook,給組件添加了一個內部state,在re-render的時候React會保留這個state。數組

  • useState的參數:ide

    • useState的惟一的參數是state的初始值。這個初始值沒必要須是object,能夠是任意類型的值
  • useState的返回值:返回了2個東西函數

    • 當前state
    • 一個能夠更新state的函數。這個函數和setState很像,不過它不會將舊state和新state給merge到一塊兒。

聲明多個state變量

一個組件裏能夠聲明多個state變量學習

function ExampleWithManyStates() {
  // Declare multiple state variables!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}
複製代碼

啥是Hook?

Hook就是一個鉤子函數,用Hook就能從函數組件裏hook到React state和生命週期。ui

Hook不能在class裏使用spa

React提供了許多內置Hook,你也能夠寫自定義Hook。咱們先學習內置Hook插件

Effect Hook(反作用鉤子)

  • 啥是反作用?
    • 好比說獲取數據、訂閱消息、手動修改DOM,這種操做就叫反作用(「side effects」 ( 或者簡稱「effects」))。
  • 爲啥叫反作用?
    • 第一,這些操做可能影響其餘組件
    • 第二,不能在render的時候執行這些操做。

Effect Hook, useEffect,給函數組件提供了執行反作用的能力。useEffect的用處和class組件裏的componentDidMount, componentDidUpdate, and componentWillUnmount同樣,可是不像class組件裏的3個API,useEffect被整合成了一個單獨的API。code

舉個例子,下面這個組件在React更新DOM後會更改文檔標題component

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

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

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

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

useEffect的參數就是反作用函數,這個函數在React Update以後執行。

useEffect要在組件內部定義,這樣才能獲取到組件的props和state。

默認狀況下,react在每次render的過程當中(包括初次渲染)都會執行反作用函數。

Effect Hook接收的反作用函數的返回值能夠是一個函數,這個函數告訴React如何清理這些反作用。

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

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

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);

    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

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

return的函數將在2個時刻調用:

  1. 組件unmount的時候
  2. 前面說過,反作用函數在每次render的過程當中都會執行,而反作用函數執行以前,將會調用這個return的函數(固然若是傳遞給ChatAPI的props.friend.id沒有改變,也有辦法告訴React跳太重新訂閱)

相似useState,一個組件能夠定義多個effect

function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  // ...
複製代碼

Hook的規則

有2點

  1. 在最上層調用Hook。不能在循環、判斷或者嵌套的函數中調用
  2. 只在React 函數組件和你自定義的Hook裏調用Hook

構建自定義Hook

前面介紹了一個調用useState和useEffect Hooks的FriendStatus組件來訂閱朋友的在線狀態。假設咱們還但願在另外一個組件中重用此訂閱邏輯。

首先,咱們將這個邏輯提取到一個名爲useFriendStatus的自定義Hook中:

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

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}
複製代碼

useFriendStatus將friendID做爲參數,返回isOnline。

如今咱們能夠從兩個組件中使用它:

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
複製代碼
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li>
  );
}
複製代碼
  • Hook是重用的是狀態邏輯而不是狀態自己。
    • Hook是重用的是狀態邏輯而不是狀態自己。每次調用Hook獲得的狀態徹底獨立 ,因此能夠在一個組件中屢次調用相同的自定義Hook。
  • 使用use做爲自定義Hook的名字的開頭
    • 自定義Hook更像是一種約定(convention)而非特性(feature),若是一個函數是」use「開頭的,而且調用了其餘Hook,那咱們就稱之爲一個自定義Hook。
    • useSomething這種命名約定能在使用Hook的時候幫助linter插件定位bug。

其餘Hook

useContext能在不引入嵌套的狀況下訂閱React上下文

function Example() {
  const locale = useContext(LocaleContext);
  const theme = useContext(ThemeContext);
  // ...
}
複製代碼

useReducer能用reduce管理複雜組件的本地狀態

function Todos() {
  const [todos, dispatch] = useReducer(todosReducer);
  // ...
複製代碼
相關文章
相關標籤/搜索