您好,登錄后才能下訂單哦!
在使用 React 編寫組件的時候,我們常常會碰到兩個不同的組件之間需要共享狀態(tài)情況,而通常的做法就是提升狀態(tài)到父組件。但是這樣做會有一個問題,就是盡管只有兩個組件需要這個狀態(tài),但是因為把狀態(tài)提到了父組件,那么在狀態(tài)變化的時候,父組件以及其下面的所有子組件都會重新 render,如果你的父組件比較復(fù)雜,包含了其他很多子組件的話,就有可能引起性能問題。
Redux 通過把狀態(tài)放在全局的 store 里,然后組件去訂閱各自需要的狀態(tài),當(dāng)狀態(tài)發(fā)生變化的時候,只有那些訂閱的狀態(tài)發(fā)生變化的組件才重新 render,這樣就避免了上面說的提升狀態(tài)所帶來的副作用。但是,當(dāng)我們在寫一個 React 組件庫的時候,redux 加 react-redux 的組合可能就有點太重了。所以我們可以自己寫一個簡單的 store,來實現(xiàn)類似 Redux 的訂閱模式。
參考 Redux 的實現(xiàn)來寫一個簡版的 createStore:
function createStore(initialState) { let state = initialState; const listeners = []; function setState(partial) { state = { ...state, ...partial, }; for (let i = 0; i < listeners.length; i++) { listeners[i](); } } function getState() { return state; } function subscribe(listener) { listeners.push(listener); return function unsubscribe() { const index = listeners.indexOf(listener); listeners.splice(index, 1); }; } return { setState, getState, subscribe, }; }
我們的 createStore 非常簡單,算上空行也只有 33 行,總共暴露了 3 個方法,沒有 Redux 里的 dispatch 和 reducer,直接通過 setState 方法改變狀態(tài)。下面我們來用它一個計數(shù)器的例子。
class Counter extends React.Component { constructor(props) { super(props); // 初始化 store this.store = createStore({ count: 0, }); } render() { return ( <div> <Buttons store={store} /> <Result store={store} /> </div> ) } } class Buttons extends React.Component { handleClick = (step) => () => { const { store } = this.props; const { count } = store.getState(); store.setState({ count: count + step }); } render() { return ( <div> <button onClick={this.handleClick(1)}>+</button> <button onClick={this.handleClick(1)}>-</button> </div> ); } } class Result extends React.Component { constructor(props) { super(props); this.state = { count: props.store.getState().count, }; } componentDidMount() { this.props.store.subscribe(() => { const { count } = this.props.store.getState(); if (count !== this.state.count) { this.setState({ count }); } }); } render() { return ( <div>{this.state.count}</div> ); }; }
例子中 Buttons 里通過 store.setState 來改變 store 中的狀態(tài),并不會引起整個 Counter 的重新 render,但是因為 Result 中訂閱了 store 的變化,所以當(dāng) count 有變化的時候就可以通過改變自己組件內(nèi)的狀態(tài)來重新 render,這樣就巧妙地避免了不必須要的 render。
最后,上面的 createStore 雖然只有幾十行代碼,我還是把它寫成了一個叫 mini-store 庫放在 GitHub 上,并且提供了類似 Redux 的 Provider 和 connect 方法,總共加起來也就 100 多行代碼。如果你也在寫 React 組件庫,需要管理一個復(fù)雜組件的狀態(tài),不妨試試這個優(yōu)化方式。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。