翻譯:瘋狂的技術宅css
原文:blog.logrocket.com/returning-n…前端
未經容許嚴禁轉載react
在 React 16 中爲了防止沒必要要的 DOM 更新,容許你決定是否讓 .setState
更來新狀態。在調用 .setState
時返回 null
將再也不觸發更新。前端工程化
咱們將經過重構一個 mocktail (一種不含酒精的雞尾酒)選擇程序來探索它是如何工做的,即便咱們選擇相同的 mocktail 兩次也會更新。bash
目錄結構以下所示:app
src
|-> App.js
|-> Mocktail.js
|-> index.js
|-> index.css
|-> Spinner.js
複製代碼
咱們的程序將顯示一個被選中的 mocktail。能夠經過單擊按鈕來選擇或切換 mocktail。這時會加載一個新的 mocktail,並在加載完成後渲染出這個 mocktail 的圖像。函數
App
組件的父組件有 mocktail
狀態和 updateMocktail
方法,用於處理更新 mocktail。工具
import React, { Component } from 'react';
import Mocktail from './Mocktail';
class App extends Component {
state = {
mocktail: ''
}
updateMocktail = mocktail => this.setState({ mocktail })
render() {
const mocktails = ['Cosmopolitan', 'Mojito', 'Blue Lagoon'];
return (
<React.Fragment>
<header>
<h1>Select Your Mocktail</h1>
<nav>
{
mocktails.map((mocktail) => {
return <button
key={mocktail}
value={mocktail}
type="button"
onClick={e => this.updateMocktail(e.target.value)}>{mocktail}</button>
})
}
</nav>
</header>
<main>
<Mocktail mocktail={this.state.mocktail} />
</main>
</React.Fragment>
);
}
}
export default App;
複製代碼
在 button
元素的 onClick
事件上調用 updateMocktail
方法,mocktail
狀態被傳遞給子組件 Mocktail
。性能
Mocktail
組件有一個名爲 isLoading
的加載狀態,當其爲 true
時會渲染 Spinner
組件。動畫
import React, { Component } from 'react';
import Spinner from './Spinner';
class Mocktail extends Component {
state = {
isLoading: false
}
componentWillReceiveProps() {
this.setState({ isLoading: true });
setTimeout(() =>
this.setState({
isLoading: false
}), 500);
}
render() {
if (this.state.isLoading) {
return <Spinner/>
}
return (
<React.Fragment>
<div className="mocktail-image">
<img src={`img/${this.props.mocktail.replace(/ +/g, "").toLowerCase()}.png`} alt={this.props.mocktail} />
</div>
</React.Fragment>
);
}
}
export default Mocktail;
複製代碼
在 Mocktail
組件的 componentWillReceiveProps
生命週期方法中調用 setTimeout
,將加載狀態設置爲 true
達 500 毫秒。
每次使用新的 mocktail
狀態更新 Mocktail
組件的 props 時,它會用半秒鐘顯示加載動畫,而後渲染 mocktail 圖像。
如今的問題是,即便狀態沒有改變,mocktail
狀態也會被更新,同時觸發從新渲染 Mocktail
組件。
例如每當單擊 Mojito 按鈕時,咱們都會看到程序對 Mojito 圖像進行了沒必要要地從新渲染。 React 16 對狀態性能進行了改進,若是新的狀態值與其現有值相同的話,經過在 setState
中返回 null
來防止來觸發更新。
如下是咱們將要遵循的步驟,來防止沒必要要的從新渲染:
null
null
將不會更新狀態和觸發組件從新渲染首先,在 app
組件的 updateMocktail
方法中,建立一個名爲 newMocktail
的常量,並用傳入的 mocktail
值爲其賦值。
updateMocktail = mocktail => {
const newMocktail = mocktail;
this.setState({
mocktail
})
}
複製代碼
由於咱們須要基於以前的狀態檢查和設置狀態,而不是傳遞 setState
和 object
,因此咱們須要傳遞一個之前的狀態做爲參數的函數。而後檢查 mocktail
狀態的新值是否與現有值相同。
若是值相同,setState
將返回 null
。不然 setState
返回更新的 mocktail
狀態,這將觸發使用新狀態從新渲染 Mocktail
組件。
updateMocktail = mocktail => {
const newMocktail = mocktail;
this.setState(state => {
if (state.mocktail === newMocktail) {
return null;
} else {
return { mocktail };
}
})
}
複製代碼
如今單擊按鈕仍會加載其各自的 mocktail 圖像。可是,若是咱們再次單擊同一個mocktail按鈕,React 不會從新渲染 Mocktail
組件,由於 setState
返回 null
,因此狀態沒有改變,也就不會觸發更新。
我在下面的兩個 GIF 中突出顯示了 React DevTools 中的更新:
**注意:**我在這裏換了一個深色主題,以便更容易觀察到 React DOM 中的更新。
本文介紹了在 React 16 中怎樣從 setState
返回 null
。我在下面的 CodeSandbox
中添加了 mocktail
選擇程序的完整代碼,供你使用和 fork。
CodeSandbox:codesandbox.io/embed/vj8wk…
經過使用 null
能夠防止沒必要要的狀態更新和從新渲染,這樣使咱們的程序執行得更快,從而改善程序的用戶體驗。
用戶偶然發現咱們的產品,他們對產品的見解直接反映了對公司及其產品的見解,所以咱們須要以天然和直觀的方式圍繞用戶的指望去構建體驗。
但願本文可以對你有所幫助。感謝閱讀!