原文地址: medium.com/better-prog…
譯文地址:github.com/xiao-T/note…
本文版權歸原作者所有,翻譯僅用於學習。
我們是否還需要 Redux 和 Mobx 這類的狀態管理框架?
引言
React hooks 的引入無疑改變的了 state 管理的現狀。
在此之前,很難在元件之間共享 state 相關的邏輯。現在,我們可以很簡單的通過抽象一個 hook 來處理(例如:useUserLogin
)。
這就引出了問題,為什麼我們還需要狀態管理框架?在這篇文章中,我將展示我的決策過程:如何管理 state
。關於在2020年我們是否還需要 state 管理框架,我也會分享我的觀點。
有什麼變化?
在有 Hooks 之前,我們是如何定義 state 的?基本上,有兩種選擇:在元件內部定義本地 state,或者用一個 state 管理框架設定全域性的 state (例如:Mobx/Redux)。
本地 state (hooks 之前)
export class UserList extends Component {
state = {
isLoading: false,
hasError: false,
users: []
}
searchUsers(value) {
this.setState({isLoading: true});
api.get(`/users?searchKey=${value}`)
.then((data) => this.setState({users: data}))
.catch(() => this.setState({hasError: true}))
.finally(() => this.setState({loading: false}));
}
render() {
if (this.state.isLoading) {
// render loading spinner
}
if (this.state.hasError) {
// render error message
}
return (
<div>
<input onChange={(event) => this.searchUsers(event.target.value)} />
</div>
)
}
}
複製程式碼
在接下來我們會說明只有這兩個選擇時帶來的問題。假設,我們的 state 不必設為全域性,但是,我們希望可以在多個元件複用 state,我們該如何定義本地 state。
在上面的演示中,我們或許想複用 loading 和 error state,在 Hooks 之前,是不可能的。唯一的選擇是需要利用 Redux 來複用它。在 Redux 中,任何需要搜尋使用者的元件只需簡單 dispatch 一個 action(searchUsers()
)和監聽全域性 state 的變化即可。
然而,使用這些全域性 state(Redux/Mobx)會帶來一些問題:
- 更多的樣板程式碼
- 複雜的資料流
- 多個元件同時維護全域性 state,這可以能會帶來意想不到的副作用。
解決方案:React Hooks!
謝天謝地 React v16.8 引入的 Hooks。從這時起,在做元件之間共享 state 相關的邏輯變得可行。
在下面的演示中,我們可以共享 loading 和 error 的行為:
import {useState} from 'react';
const useRequestHandler = () => {
const [isLoading, setLoading] = useState(false);
const [hasError, setError] = useState(false);
const [data, setData] = useState(null);
const handleRequest = (request) => {
setLoading(true);
setError(false);
return api.get(request)
.then(setData)
.catch(() => setError(true))
.finally(() => setLoading(false))
};
return {isLoading, hasError, data, handleRequest};
};
const UserList = () => {
const {data, isLoading, hasError, handleRequest} = useRequestHandler();
const searchUsers = (value) => handleRequest(`/users?searchKey=${value}`);
return (
<React.Fragment>
{data.map(u => <p>{u.name}</p>)}
</React.Fragment>
)
}
複製程式碼
更多好處:如果,多個元件需要搜尋使用者列表的功能,我們也可以自定義 useUserSearch
hook。
然而,hooks 並不是銀彈。把 state 儲存在 hook 中,並不意味著它就變成了單例物件,它只是繫結在一個元件中。在某些情況下,我們只想保留一個例項 state 物件(例如:只載入一次使用者資訊)。這是 state 管理框架提供的功能。
如何,何時,何地管理 state
現在,可以在多個元件之間共享 state 相關邏輯了,那我們怎麼決定 state 儲存在元件內(本地),還是儲存在 state 管理框架中(全域性)呢?
下面的圖片展示了我的決策過程。
State 管理框架有什麼好處呢?
現在,我們知道如何在全域性和本地做抉擇了。但是,在2020年為什麼還需要 state 管理框架呢?這相比 React Hooks 有什麼好處呢?
有以下幾個好處:
- 全域性定義,也代表只有一個例項物件
- 只會載入一次遠端資料
- 開發工具的支援
- 為軟體工程師提供了一種標準的開發方式
總結
我們看到 React Hooks 已經攪動了 state 管理的格局。由於它們的引入,在元件之間共享 state 相關邏輯變得更加簡單。
然而,Hooks 並不是銀彈,我們仍舊需要 state 管理框架。這也並不是說要讓所有的 state 都是全域性的 — 大多情況下讓其保留在元件之間更加好。只有在有絕對必要的情況下,才把 state 移動到 state 管理框架中。