React 16.7.0-alpha hooks 之總體預覽

轉載於免費視頻網 www.rails365.nethtml

以前咱們介紹了使用hooks的緣由,在開始介紹api以前,如今咱們先來總體的預覽下這些api。 從上篇的介紹能夠知道,Hook是向後兼容的,有react開發經驗的你看起來會更順暢。react

是一個快節奏的概述。若是你感到困惑,能夠看下上面提到的介紹裏的動機:git

詳細說明 閱讀動機以瞭解咱們爲什麼將Hooks引入React。github

State Hook

看下面的例子,他是一個計數器api

import { 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(咱們將在稍後討論這意味着什麼)。能夠看到,在這個函數組件裏,咱們向他添加一些本地狀態。React將在從新渲染之間保留這狀態。 useState返回一對:當前狀態值(count)和容許你更新狀態的函數(setCount)。你能夠從事件處理程序或其餘位置調用此函數。這個函數相似於類中的this.setState,可是它不會將舊狀態和新狀態合併在一塊兒。(咱們將在使用State Hook中顯示一個將useStatethis.state進行比較的示例。)數組

useState的惟一參數是初始狀態。 在上面的例子中,它是0,由於咱們的計數器從零開始。請注意,與this.state不一樣,此處的狀態沒必要是對象 - 儘管能夠是任何你想要的。初始狀態參數僅在第一次渲染期間使用。函數

聲明多個state

你能夠在一個組件中屢次使用State Hookui

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

數組解構語法容許咱們爲經過調用useState聲明的狀態變量賦予不一樣的名稱。這些名稱不是useState API的一部分。相反,React假定若是屢次調用useState,則在每次渲染期間以相同的順序執行。咱們將回到爲何這種方法有效以及什麼時候有用。this

什麼是Hook

鉤子是容許從功能組件(function component)「掛鉤」React狀態和生命週期功能的功能。鉤子在類內部不起做用 - 它們容許你在沒有類的狀況下使用React (咱們不建議你在一晚上之間重寫現有組件,但若是你願意,能夠開始在新組件中使用Hook。)spa

React提供了一些像useState這樣的內置Hook。你還能夠建立自定義Hook以在不一樣組件之間重用有狀態行爲。咱們先來看看內置的Hooks

詳細說明 你能夠在使用State Hook中瞭解更多信息。

Effect Hook

你以前可能已經從React組件執行數據提取,訂閱或手動更改DOM。咱們將這些操做稱爲「反作用」(或簡稱爲「效果」),由於它們會影響其餘組件,而且在渲染過程當中沒法完成。

Effect Hook中的useEffect增長了在功能組件執行反作用的功能。它與React類中的componentDidMountcomponentDidUpdatecomponentWillUnmount具備相同的用途,但統一爲單個API。(咱們將在使用Effect Hook時顯示將useEffect與這些方法進行比較的示例。)

例如,下面的組件將在React更新DOM後設置文檔標題:

import { useState, useEffect } from 'react';

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

  // 相似componentDidMount 和 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運行你的‘效果’函數當刷新對DOM的更改後(你能夠認爲是render以後)。 效果在組件內聲明,所以能夠訪問其propsstate。默認狀況下,React在每次渲染後運行效果 - 包括第一次渲染。 (咱們將更多地討論使用effect hook與類生命週期的比較。)

Effects還能夠經過指定返回函數來清理他們。看下面的這個例子:

import { 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';
}
複製代碼

在這個示例中,當組件卸載時,以及在因爲後續渲染而從新運行效果以前,React將取消訂閱咱們的ChatAPI。(若是你願意的話,若是咱們傳遞給ChatAPIprops.friend.id沒有改變,有辦法告訴React跳太重新訂閱。)

就像使用useState同樣, 你也能夠在組件中使用多個效果:

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);
  }
  // ...
}
複製代碼

Hooks容許你經過哪些部分相關(例如添加和刪除訂閱)來組織組件中的反作用,而不是基於生命週期方法強制拆分。

詳細說明 你能夠在使用Effect Hook中瞭解更多信息。

Hooks的規則

鉤子是JavaScript函數,但它們強加了兩個額外的規則:

  • 只能在頂層調用Hooks。不要在循環,條件或嵌套函數中調用Hook
  • 僅從React功能組件調用Hooks 不要從常規JavaScript函數中調用Hook。 (還有另外一個有效的地方叫Hooks - 你本身的定製Hooks。咱們立刻就會了解它們。)

詳細說明 你能夠在Rules Hook中瞭解更多信息。

Custom Hooks

有時,咱們但願在組件之間重用一些有狀態邏輯的部分。傳統上,這個問題有兩個流行的解決方案:高階組件渲染道具Custom Hooks容許你執行這樣的操做,而且無需向樹中添加更多組件。在上面咱們介紹了一個調用useStateuseEffect HooksFriendStatus組件來訂閱朋友的在線狀態。假設咱們還但願在另外一個組件中重用此訂閱邏輯。 首先,咱們將這個邏輯提取到一個名爲useFriendStatus的自定義Hook中:

import { 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;
}
複製代碼

它將friendID做爲參數,並返回咱們的朋友是否在線。 如今咱們能夠從兩個組件中使用它:

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兩次。

custom hook更像是一種約定而非功能。若是函數的名稱以use開頭而且它調用其餘Hook,咱們說它是一個Custom HookuseSomething命名約定是linter插件如何使用Hooks在代碼中查找錯誤的。

詳細說明 你能夠在Writing Custom Hooks中瞭解更多信息。

Other Hooks

你可能會發現一些不太經常使用的內置Hook頗有用。例如,useContext容許訂閱React上下文而不引入嵌套:

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

useReducer容許使用reducer管理複雜組件的本地狀態:

function Todos() {
  const [todos, dispatch] = useReducer(todosReducer);
  // ...
}
複製代碼

詳細說明 你能夠在 Hooks API Reference.中瞭解更多信息。

本文原文檔

下一章節state前往此處

相關文章
相關標籤/搜索