React 16.8終於帶來了穩定版的hooks。
什麼是hooks?
hooks可以讓你在不編寫類的情況下使用state和React的其他功能。你還可以構建自己的hooks,在組件之間共享可重用的有狀態邏輯。
如果你之前從未聽說過hooks,可以參考以下這些資源:
-
“Introducing hooks”解釋了我們爲React添加hooks功能;
-
“hooks at a Glance”是對內置的hooks進行了快速的介紹;
-
“Building Your Own hooks ”演示瞭如何使用自定義hooks重用代碼;
-
“Making Sense of React hooks”探討了hooks帶來的新的可能性;
-
usehooks.com列出了由社區維護的hooks實踐和演示示例。
你不一定要現在學習hooks,它並沒有帶來重大變化,我們也沒有計劃從React中移除類。hooks的FAQ談到了hooks的逐步採用策略。
不要進行重大重寫
我們不建議你爲了能夠馬上採用hooks而對現有應用程序進行重大重寫。相反,可以在一些新組件中嘗試使用hooks,並讓我們知道你的想法。使用hooks的代碼仍然可以與使用類的現有代碼並存。
從今天起就可以使用hooks了嗎?
是的!從16.8.0開始,React包含了穩定版本的React hooks實現:
-
React DOM
-
React DOM Server
-
React Test Renderer
-
React Shallow Renderer
請注意,要使用hooks,所有React包都需要升級到16.8.0或更高版本。如果你忘記更新某個包(例如React DOM),hooks將無法工作。
React Native將在0.59版本中支持hooks。
工具支持
React DevTools現在支持React hooks,最新Flow和TypeScript定義也支持它們。建議啓用一個叫作eslint-plugin-react-hooks的lint規則來強制執行hooks的最佳實踐,它很快會被包含在Create React App中。
下一步
我們在最近發佈的React路線圖中描述了未來幾個月的計劃。
請注意,React hooks還沒有涵蓋類的所有用例,但已經非常接近了。目前,只有getSnapshotBeforeUpdate()和componentDidCatch()方法沒有等效的hooks API,而且這些生命週期方法相對不那麼常見。如果你願意,應該可以在大部分新代碼中使用hooks。
在hooks還處於alpha狀態的時候,React社區就已經使用hooks爲動畫、表單、訂閱、與其他庫集成等創建了很多有趣的示例。我們也感到很興奮,因爲hooks讓代碼重用變得更加容易,可以幫助你以更簡單的方式開發組件併爲用戶帶來更出色的用戶體驗。
測試hooks
我們在這個版本中添加了一個叫作ReactTestUtils.act()的API,它可以確保測試中的行爲與在瀏覽器中的行爲更加接近。我們建議將渲染和觸發組件更新的代碼包裝到act()調用中。測試庫也可以用它來包裝它們的API(例如,react-testing-library的render和fireEvent就是這樣做的)。
例如,這個頁面中的計數器示例可以像這樣測試:
import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
it('can render and update a counter', () => {
// Test first render and effect
act(() => {
ReactDOM.render(<Counter />, container);
});
const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 0 times');
expect(document.title).toBe('You clicked 0 times');
// Test second render and effect
act(() => {
button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
});
expect(label.textContent).toBe('You clicked 1 times');
expect(document.title).toBe('You clicked 1 times');
});
對act()的調用也會刷新它們內部的狀態。
如果你需要測試自定義hooks,可以在測試中創建一個組件,並在這個組件上使用hooks,然後就可以測試你的組件。
爲了減少樣板代碼,我們建議使用react-testing-library,你可以像最終用戶使用組件那樣對組件進行測試。
安裝
React v16.8.0現在可以從npm註冊表中獲得。
要使用Yarn安裝React 16,請運行:
yarn add react@^16.8.0 react-dom@^16.8.0
要使用npm安裝React 16,請運行:
npm install --save react@^16.8.0 react-dom@^16.8.0
我們還通過CDN提供了UMD版本:
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
更詳細的安裝說明請參閱官方文檔。
用於React hooks的ESLint插件
注意:
如上所述,我們強烈建議使用eslint-plugin-react-hooks lint規則。
如果你正在使用Create React App,可以等待下一版本react-scripts發佈,它將包含這個規則,而不是手動去配置ESLint。
假設你已經安裝了ESLint,請運行:
# npm
npm install eslint-plugin-react-hooks@next --save-dev
# yarn
yarn add eslint-plugin-react-hooks@next --dev
然後將其添加到ESLint配置中:
{
"plugins": [
// ...
"react-hooks"
],
"rules": {
// ...
"react-hooks/rules-of-hooks": "error"
}
}
更新日誌
React
-
新增了hooks——一種在不編寫類的情況下使用state和React其他功能的方法。
-
改進了useReducer hooks延遲初始化API。
React DOM
- 在使用useState和useReducer hooks時,如果值相同則退出渲染。
- 不比較傳給useEffect/useMemo/useCallback hooks的第一個參數。
- 使用Object.is算法比較useState和useReducer的值。
- 支持傳給React.lazy()的同步thenable。
- 在嚴格模式(僅限DEV)中使用hooks兩次渲染組件以便與類的行爲相匹配。
- 在開發中對hooks順序不匹配提出警告。
- 狀態清理函數必須返回undefined或另一個函數,不允許包括null在內的其他值。
React Test Renderer
- 支持在淺渲染器中使用hooks。
- 在getDerivedStateFromProps存在的情況下修復shouldComponentUpdate中的錯誤狀態。
- 添加ReactTestRenderer.act()和ReactTestUtils.act()以進行批量更新,這樣就可以測試更接近真實的行爲。
ESLint插件:React hooks
- 初始發佈。
- 修復循環錯誤。
- 不將拋出異常視爲違反規則。
英文原文:https://reactjs.org/blog/2019/02/06/react-v16.8.0.html?from=timeline&isappinstalled=0
更多內容,請關注前端之巔。