自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Sentry 開發(fā)者貢獻(xiàn)指南-前端 React Hooks 與蟲洞狀態(tài)管理模式

開發(fā) 前端
如果有一個(gè)組件關(guān)心這個(gè)問題,使用它。如果有幾個(gè)組件在意,就用 props 分享一下。如果很多組件都關(guān)心,把它放在 context 中。

[[441055]]

什么是蟲洞狀態(tài)管理模式?

您可以逃脫的最小 state 共享量是多少?

保持你的 state。盡可能靠近使用它的地方。

如果有一個(gè)組件關(guān)心這個(gè)問題,使用它。如果有幾個(gè)組件在意,就用 props 分享一下。如果很多組件都關(guān)心,把它放在 context 中。

Context 就像一個(gè)蟲洞。它使您的組件樹彎曲,因此相距很遠(yuǎn)的部分可以接觸。

利用自定義 hooks 使這變得容易。

一個(gè)例子

構(gòu)建一個(gè)點(diǎn)擊計(jì)數(shù)器。蟲洞狀態(tài)管理模式最好通過示例來解釋 ??

CodeSandbox(示例代碼)

  • https://codesandbox.io/s/wormhole-state-pattern-5-j4w5e?file=/src/App.js

步驟 1

我們從 useState 開始,因?yàn)樗亲詈?jiǎn)單的。

  1. const ClickCounter = () => { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   function onClick() { 
  5.     setCount(count => count + 1); 
  6.   } 
  7.  
  8.   return <button onClick={onClick}>{count} +1</button>; 
  9. }; 

count 保存當(dāng)前的點(diǎn)擊次數(shù),setCount 讓我們?cè)诿看吸c(diǎn)擊時(shí)更新值。

足夠簡(jiǎn)單。

不過,外觀并不是很漂亮。讓我們用一個(gè)自定義按鈕組件和一些嵌套來改進(jìn)它。

步驟 2

我們創(chuàng)建了一個(gè)可重復(fù)使用的 PrettyButton,確保您應(yīng)用中的每個(gè)按鈕看起來都很棒。

狀態(tài)保留在 ClickCounter 組件中。

  1. const ClickCounter = () => { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   function onClick() { 
  5.     setCount(count => count + 1); 
  6.   } 
  7.  
  8.   return ( 
  9.     <> 
  10.       <p>You have clicked buttons {count} times</p> 
  11.       <div style={{ textAlign: "right" }}> 
  12.         <PrettyButton onClick={onClick}>+1</PrettyButton> 
  13.       </div> 
  14.     </> 
  15.   ); 
  16. }; 

這是必要的最少狀態(tài)共享。我們也保持了簡(jiǎn)單的狀態(tài)。

計(jì)數(shù)器組件關(guān)心點(diǎn)擊次數(shù)和計(jì)數(shù),因此它將回調(diào)作為 props 傳遞到按鈕中。函數(shù)被調(diào)用,狀態(tài)更新,組件重新渲染。

不需要復(fù)雜的操作。

步驟 3

如果我們的狀態(tài)更復(fù)雜怎么辦?我們有 2 個(gè)屬于一起的項(xiàng)。

您可以在您的狀態(tài)中保留復(fù)雜的值。效果很好。

  1. const ClickCounter = () => { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   function onClick() { 
  5.     setCount(count => count + 1); 
  6.   } 
  7.  
  8.   return ( 
  9.     <> 
  10.       <p>You have clicked buttons {count} times</p> 
  11.       <div style={{ textAlign: "right" }}> 
  12.         <PrettyButton onClick={onClick}>+1</PrettyButton> 
  13.       </div> 
  14.     </> 
  15.   ); 
  16. }; 

我們已將 count 拆分為一個(gè)對(duì)象 – { A, B }。

現(xiàn)在單個(gè)狀態(tài)可以保存多個(gè)值。單獨(dú)按鈕點(diǎn)擊的單獨(dú)計(jì)數(shù)。

React 使用 JavaScript 相等來檢測(cè)重新渲染的更改,因此您必須在每次更新時(shí)制作完整狀態(tài)的副本。這在大約 10,000 個(gè)元素時(shí)變慢。

您也可以在這里使用 useReducer。特別是當(dāng)您的狀態(tài)變得更加復(fù)雜并且項(xiàng)目經(jīng)常單獨(dú)更新時(shí)。

使用 useReducer 的類似狀態(tài)如下所示:

  1. const [state, dispatch] = useReducer((action, state) => { 
  2.     switch (action.type) { 
  3.         case 'A'
  4.             return { ...state, A: state.A + 1 } 
  5.         case 'B'
  6.             return { ...state, A: state.A + 1 } 
  7.     } 
  8. }, { A: 0, B: 0}) 
  9.  
  10. function onClickA() { 
  11.     dispatch({ type: 'A' }) 

你的狀態(tài)越復(fù)雜,這就越有意義。

但我認(rèn)為那些 switch 語句很快就會(huì)變得混亂,而且你的回調(diào)函數(shù)無論如何都已經(jīng)是動(dòng)作了。

步驟 4

如果我們想要 2 個(gè)按鈕更新相同的狀態(tài)怎么辦?

您可以將 count 和 setCount 作為 props 傳遞給您的組件。但這變得越來越混亂。

  1. const AlternativeClick = ({ count, setCount }) => { 
  2.   function onClick() { 
  3.     setCount(count => { 
  4.       return { ...count, B: count.B + 1 }; 
  5.     }); 
  6.   } 
  7.  
  8.   return ( 
  9.     <div style={{ textAlign: "left" }}> 
  10.       You can also update B here 
  11.       <br /> 
  12.       <PrettyButton onClick={onClick}>B +1</PrettyButton> 
  13.       <p>It's {count.B} btw</p> 
  14.     </div> 
  15.   ); 
  16. }; 

我們創(chuàng)建了一個(gè)難以移動(dòng)并且需要理解太多父邏輯的組件。關(guān)注點(diǎn)是分裂的,抽象是奇怪的,我們?cè)斐闪嘶靵y。

你可以通過只傳遞它需要的狀態(tài)部分和一個(gè)更自定義的 setCount 來修復(fù)它。但這是很多工作。

步驟 5

相反,您可以使用蟲洞與自定義 hook 共享狀態(tài)。

您現(xiàn)在有 2 個(gè)共享狀態(tài)的獨(dú)立組件。將它們放在您的代碼庫中的任何位置,它 Just Works?。

需要在其他地方訪問共享狀態(tài)?添加 useSharedCount hook,瞧。

這是這部分的工作原理。

我們有一個(gè) context provider,里面有一些操作:

  1. export const SharedCountProvider = ({ children }) => { 
  2.   // replace with useReducer for more flexiblity 
  3.   const [state, setState] = useState(defaultState); 
  4.  
  5.   const [contextValue, setContextValue] = useState({ 
  6.     state, 
  7.     // dispatch // from your reducer 
  8.     // this is where a reducer comes handy when this grows 
  9.     setSharedCount: (key, val) => { 
  10.       setState(state => { 
  11.         return { ...state, [key]: val }; 
  12.       }); 
  13.     } 
  14.     // other stuff you need in context 
  15.   }); 
  16.  
  17.   // avoids deep re-renders 
  18.   // when instances of stuff in context change 
  19.   useEffect(() => { 
  20.     setContextValue(currentValue => ({ 
  21.       ...currentValue, 
  22.       state 
  23.     })); 
  24.   }, [state]); 
  25.  
  26.   return ( 
  27.     <SharedCountContext.Provider value={contextValue}> 
  28.       {children} 
  29.     </SharedCountContext.Provider> 
  30.   ); 
  31. }; 

Context Provider 使用豐富的 state 變量來保持您的狀態(tài)。這里對(duì)我們來說是 { A, B }。

contextValue 是一個(gè)更豐富的狀態(tài),它也包含操作該狀態(tài)所需的一切。通常,這將是來自您的 reducer 的 dispatch 方法,或者像我們這里的自定義狀態(tài)設(shè)置器。

我們的 setSharedCount 方法獲取一個(gè) key 和一個(gè) val 并更新該部分狀態(tài)。

  1. setSharedCount("B", 10); 

然后我們有一個(gè)副作用,它觀察 state 的變化并在需要時(shí)觸發(fā)重新渲染。這避免了每次我們重新定義我們的 dispatch 方法或其他任何東西時(shí)的深度重新渲染。

使 React 樹更穩(wěn)定 ??

在這個(gè) provider 中呈現(xiàn)的每個(gè)組件都可以使用這個(gè)相同的自定義 hook 來訪問它需要的一切。

  1. export function useSharedCount() { 
  2.   const { state, setSharedCount } = useContext(SharedCountContext); 
  3.  
  4.   function incA() { 
  5.     setSharedCount("A", state.A + 1); 
  6.   } 
  7.  
  8.   function incB() { 
  9.     setSharedCount("B", state.B + 1); 
  10.   } 
  11.  
  12.   return { count: state, incA, incB }; 

自定義 hook 利用 React Context 共享狀態(tài),定義更簡(jiǎn)單的 incA 和 incB 輔助方法,并返回它們的狀態(tài)。

這意味著我們的 AlternativeClick 組件可以是這樣的:

  1. import { 
  2.   useSharedCount 
  3. from "./SharedCountContextProvider"
  4.  
  5. const AlternativeClick = () => { 
  6.   const { count, incB } = useSharedCount(); 
  7.  
  8.   return ( 
  9.     <div style={{ textAlign: "left" }}> 
  10.       You can also update B here 
  11.       <br /> 
  12.       <PrettyButton onClick={incB}>B +1</PrettyButton> 
  13.       <p>It's {count.B} btw</p> 
  14.     </div> 
  15.   ); 
  16. }; 

從自定義 hook 獲取 count 和 incB。使用它們。

性能怎么樣?

很好。

盡可能少地共享 state。對(duì)應(yīng)用程序的不同部分使用不同的 context provider。

不要讓它成為 global,除非它需要是 global 的。包裹你可以逃脫的樹的最小部分。

復(fù)雜度如何?

什么復(fù)雜度?保持小。不要把你不需要的東西塞進(jìn)去。

討厭管理自己的狀態(tài)

看到我們 SharedCountProvider 中處理狀態(tài)變化的部分了嗎?這部分:

  1. const [contextValue, setContextValue] = useState({ 
  2.     state, 
  3.     // dispatch // from your reducer 
  4.     // this is where a reducer comes handy when this grows 
  5.     setSharedCount: (key, val) => { 
  6.       setState(state => { 
  7.         return { ...state, [key]: val }; 
  8.       }); 
  9.     } 
  10.     // other stuff you need in context 
  11.   }); 

為此,您可以使用 XState。或者 reducer。甚至 Redux,如果你真的想要的話。

不過,如果你使用 Redux,你不妨一路走下去 ??

頂級(jí)開源項(xiàng)目是如何使用的?(Sentry)

organizationContext.tsx(詳細(xì)代碼)

  • https://github.com/getsentry/sentry/blob/master/static/app/views/organizationContext.tsx

Refs

Wormhole state management 

https://swizec.com/blog/wormhole-state-management/

 

責(zé)任編輯:武曉燕 來源: 黑客下午茶
相關(guān)推薦

2021-12-15 20:06:48

ReactJSSentry開發(fā)者

2022-01-11 20:42:54

開發(fā)Sentry標(biāo)志

2022-01-17 19:34:43

SentryWeb APISentry API

2022-01-15 23:33:47

SentryPyCharm配置

2022-01-18 23:26:45

開發(fā)

2022-01-02 23:26:08

開發(fā)SDK Sentry

2021-12-25 22:31:55

Sentry 監(jiān)控SDK 開發(fā) 性能監(jiān)控

2022-01-21 21:33:03

開發(fā)JavaScript應(yīng)用

2022-01-16 22:16:59

數(shù)據(jù)庫Sentry開發(fā)者

2022-01-13 20:13:31

元宇宙搜索引擎

2022-01-03 22:59:30

開發(fā)SDK數(shù)據(jù)

2021-12-31 18:35:40

監(jiān)控Sentry開發(fā)

2022-01-02 06:59:43

SentrySDK 開發(fā)客戶端報(bào)告

2022-01-19 19:49:53

Sentry瀏覽器SDK

2021-12-16 20:12:37

后端開發(fā)Sentry

2022-01-20 19:49:10

Sentry開發(fā)Scope

2021-06-03 09:31:56

React狀態(tài)模式

2018-06-06 14:03:19

2025-01-14 00:00:00

2015-07-22 16:08:46

OpenStack開源貢獻(xiàn)代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)