React 16.7.0-alpha hooks 之規則

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

HooksJavaScript函數,但在使用它們時須要遵循兩個規則。咱們提供了一個linter插件來自動執行這些規則:git

只能夠在頂層調用Hook

不要在循環,條件或嵌套函數中調用Hook。 相反,老是在React函數的頂層使用Hooks。經過遵循此規則,能夠確保每次組件呈現時都以相同的順序 調用Hook。這就是容許React在多個useStateuseEffect調用之間正確保留Hook狀態的緣由。 (若是你很好奇, 咱們將在下面深刻解釋。)github

只從React Functions調用Hooks

不要從常規JavaScript函數中調用Hook 相反,你能夠:shell

  • 從React函數組件調用Hooks。
  • 從自定義Hooks調用Hooks(後面會介紹到)

經過遵循此規則,能夠確保組件中的全部有狀態邏輯從其源代碼中清晰可見。npm

ESLint Plugin

咱們發佈了一個名爲eslint-plugin-react-hooks的ESLint插件,它強制執行這兩個規則。若是您想嘗試,能夠將此插件添加到項目中:數組

npm install eslint-plugin-react-hooks@next
複製代碼
// Your ESLint configuration
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error"
  }
}
複製代碼

未來,有打算默認將此插件包含在Create React App和相似的工具包中。函數

詳細說明

以前有說過,一個組件能夠配置多個狀態變量或者效果鉤子:工具

function Form() {
  // 1. Use the name state variable
  const [name, setName] = useState('Mary');

  // 2. Use an effect for persisting the form
  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });

  // 3. Use the surname state variable
  const [surname, setSurname] = useState('Poppins');

  // 4. Use an effect for updating the title
  useEffect(function updateTitle() {
    document.title = name + ' ' + surname;
  });

  // ...
}
複製代碼

那麼React如何知道哪一個狀態對應於哪一個useState調用?答案是 React依賴於調用Hooks的順序。 咱們的示例有效,由於Hook調用的順序在每一個渲染上都是相同的:ui

// ------------
// First render
// ------------
useState('Mary')           // 1. 初始化`name`狀態變量爲 'Mary'
useEffect(persistForm)     // 2. 添加一個效果
useState('Poppins')        // 3. 初始化`surname`狀態變量爲 'Poppins'
useEffect(updateTitle)     // 4. 添加一個效果

// -------------
// Second render
// -------------
useState('Mary')           // 1. 讀取`name`狀態變量 (參數被忽略)
useEffect(persistForm)     // 2. 替換以前的效果
useState('Poppins')        // 3. 相似於上面的`name state`
useEffect(updateTitle)     // 4. 也是替換成如今的這個
// ...
複製代碼

只要Hook調用的順序在渲染之間是相同的,React就能夠將一些本地狀態與它們中的每個相關聯。可是若是咱們在條件中放置Hook調用(例如,persistForm效果)會發生什麼?spa

useState('Mary')           // 1. 讀取`name`狀態變量 (參數被忽略)
// useEffect(persistForm) // 🔴這個Hook被幹掉了
useState('Poppins')        // 🔴 2 (可是以前是第三步). 讀取`surname`狀態變量失敗
useEffect(updateTitle)     // 🔴 3 (可是以前是第四步). 替換`effect`失敗
複製代碼

React不知道第二次useState Hook調用返回什麼。 React指望此組件中的第二個Hook調用對應於persistForm效果,就像在前一個渲染中同樣,但它再也不存在。從那時起,在咱們跳過的那個以後的每一個下一個Hook調用也會移動一個,致使錯誤。

這就是爲何咱們須要在組件頂層調用Hook的緣由。 若是咱們想要有條件地運行一個效果,咱們能夠把這個條件放在咱們的Hook中:

useEffect(function persistForm() {
    // 👍 We're not breaking the first rule anymore
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });
複製代碼

請注意,若是使用提供的lint規則,則無需擔憂此問題。 可是如今你也知道爲何Hooks以這種方式工做,以及規則阻止了哪些問題。

相關文章
相關標籤/搜索