<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                最初你可能會不喜歡 Hooks: 它們就像一段音樂,只有經過幾次用心聆聽才會慢慢愛上: 當你閱讀文檔時,不要錯過關于[最重要的部分](https://reactjs.org/docs/hooks-custom.html)——創造屬于你自己的 Hooks!太多的人糾結于反對我們的觀點(class 學習成本高等)以至于錯過了 Hooks 更重要的一面,Hooks 像`functional mixins`,可以讓你創造和搭建屬于自己的 Hook。 Hooks[受啟發于一些現有技術](https://reactjs.org/docs/hooks-faq.html#what-is-the-prior-art-for-hooks),但在 Sebastian 和團隊分享他的想法之后,我才知道這些。不幸的是,這些 API 和現在在用的之間的關聯很容易被忽略,通過這篇文章,我希望可以幫助更多的人理解 Hooks 提案中爭議較大的點。 **接下來的部分需要你知道 Hook API 的`useState`和如何寫自定義 Hook。如果你還不懂,可以看看早先的鏈接。** (免責說明:文章的觀點僅代表個人想法,與 React 團隊無關。話題大且復雜,其中可能有錯誤的觀點。) * * * 一開始當你學習時你可能會震驚,Hooks 重渲染時是依賴于固定順序調用的,這里有[說明](https://reactjs.org/docs/hooks-rules.html)。 這個決定顯然是有爭議的,這也是為什么會有人[反對我們的提案](https://www.reddit.com/r/reactjs/comments/9xs2r6/sebmarkbages_response_to_hooks_rfc_feedback/e9wh4um/)。我們會在恰當的時機發布這個提案,當我們覺得文檔和講座可以足夠好的描繪它時。 如果你在關注 Hooks API 的某些點,我建議你閱讀下 Sebastian 對 1000+ 評論 RFC 的[全部回復](https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884),**足夠透澈但內容非常多,我可能會將評論中的每一段都變成自己的博客文章。(事實上,我已經[做過](https://overreacted.io/zh-hans/how-does-setstate-know-what-to-do/)一次!)** 我今天要關注一個具體部分。你可能還記得,每個 Hook 可以在組件里被多次使用,例如,我們可以用`useState`聲明[多個state](https://reactjs.org/docs/hooks-state.html#tip-using-multiple-state-variables): ~~~jsx function Form() { const [name, setName] = useState('Mary'); // State 變量 1 const [surname, setSurname] = useState('Poppins'); // State 變量 2 const [width, setWidth] = useState(window.innerWidth); // State 變量 3 useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }); function handleNameChange(e) { setName(e.target.value); } function handleSurnameChange(e) { setSurname(e.target.value); } return ( <> <input value={name} onChange={handleNameChange} /> <input value={surname} onChange={handleSurnameChange} /> <p>Hello, {name} {surname}</p> <p>Window width: {width}</p> </> ); } ~~~ 注意我們用數組解構語法來命名`useState()`返回的 state 變量,但這些變量不會連接到 React 組件上。相反,這個例子中,**React 將`name`視為「第一個 state 變量」,`surname`視為「第二個 state 變量」,以此類推**。它們在重新渲染時用*順序調用*來保證被正確識別。[這篇文章](https://juejin.im/post/5bfa929551882524cb6f413b)詳細的解釋了原因。 表面上看,依賴于順序調用只是*感覺有問題*,直覺是一個有用的信號,但它有時會誤導我們 —— 特別是當我們還沒有完全消化困惑的問題。**這篇文章,我會提到幾個經常有人提出修改 Hooks 的方案,及它們存在的問題**。 * * * 這篇文章不會詳盡無遺,如你所見,我們已經看過十幾種至數百種不同的替代方案,我們一直在[考慮](https://github.com/reactjs/react-future)替換組件 API。 諸如此類的博客很棘手,因為即使你涉及了一百種替代方案,也有人強行提出一個來:「哈哈,你沒有想到*這個*!」 在實踐中,不同替代方案提到的問題會有很多重復,我不會列舉*所有*建議的 API(這需要花費數月時間),而是通過幾個具體示例展示最常見的問題,更多的問題就考驗讀者舉一反三的能力了。?? *這不是說 Hooks 就是完美的*,但是一旦你了解其他解決方案的缺陷,你可能會發現 Hooks 的設計是有道理的。 * * * ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-1%EF%BC%9A%E6%97%A0%E6%B3%95%E6%8F%90%E5%8F%96-custom-hook)缺陷 #1:無法提取 custom hook 出乎意料的是,大多數替代方案完全沒有提到[custom hooks](https://reactjs.org/docs/hooks-custom.html)。可能是因為我們在「motivation」文檔中沒有足夠強調 custom hooks,不過在弄懂 Hooks 基本原理之前,這是很難做到的。就像雞和蛋問題,但很大程度上 custom hooks 是提案的重點。 例如:有個替代方案是限制一個組件調用多次`useState()`,你可以把 state 放在一個對象里,這樣還可以兼容 class 不是更好嗎? ~~~jsx function Form() { const [state, setState] = useState({ name: 'Mary', surname: 'Poppins', width: window.innerWidth, }); // ... } ~~~ 要清楚,Hooks 是允許這種風格寫的,你不必將 state 拆分成一堆 state 變量(請參閱參見問題解答中的[建議](https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables))。 但支持多次調用`useState()`的關鍵在于,你可以從組件中提取出部分有狀態邏輯(state + effect)到 custom hooks 中,同時可以單獨使用本地 state 和 effects: ~~~jsx function Form() { // 在組件內直接定義一些 state 變量 const [name, setName] = useState('Mary'); const [surname, setSurname] = useState('Poppins'); // 我們將部分 state 和 effects 移至 custom hook const width = useWindowWidth(); // ... } function useWindowWidth() { // 在 custom hook 內定義一些 state 變量 const [width, setWidth] = useState(window.innerWidth); useEffect(() => { // ... }); return width; } ~~~ 如果你只允許每個組件調用一次`useState()`,你將失去用 custom hook 引入 state 能力,這就是 custom hooks 的關鍵。 ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-2-%E5%91%BD%E5%90%8D%E5%86%B2%E7%AA%81)缺陷 #2: 命名沖突 一個常見的建議是讓組件內`useState()`接收一個唯一標識 key 參數(string 等)區分 state 變量。 和這主意有些出入,但看起來大致像這樣: ~~~jsx // ?? 這不是 React Hooks API function Form() { // 我們傳幾種 state key 給 useState() const [name, setName] = useState('name'); const [surname, setSurname] = useState('surname'); const [width, setWidth] = useState('width'); // ... ~~~ 這試圖擺脫依賴順序調用(顯示 key),但引入了另外一個問題 —— 命名沖突。 當然除了錯誤之外,你可能無法在同一個組件調用兩次`useState('name')`,這種偶然發生的可以歸結于其他任意 bug,但是,當你使用一個*custom hook*時,你總會遇到想添加或移除 state 變量和 effects 的情況。 這個提議中,每當你在 custom hook 里添加一個新的 state 變量時,就有可能破壞使用它的任何組件(直接或者間接),因為*可能已經有同名的變量*位于組件內。 這是一個沒有[應變而優](https://juejin.im/post/5c665e44518825622f12e37c)的 API,當前代碼可能看起來總是「優雅的」,但應對需求變化時十分脆弱,我們應該從[錯誤](https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html#mixins-cause-name-clashes)中吸取教訓。 實際中 Hooks 提案通過依賴順序調用來解決這個問題:即使兩個 Hooks 都用`name`state 變量,它們也會彼此隔離,每次調用`useState()`都會獲得獨立的 「內存單元」。 我們還有其他一些方法可以解決這個缺陷,但這些方法也有自身的缺陷。讓我們加深探索這個問題。 ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-3%EF%BC%9A%E5%90%8C%E4%B8%80%E4%B8%AA-hook-%E6%97%A0%E6%B3%95%E8%B0%83%E7%94%A8%E4%B8%A4%E6%AC%A1)缺陷 #3:同一個 Hook 無法調用兩次 給`useState`「加key」的另一種衍生提案是使用像 Symbol 這樣的東西,這樣就不沖突了對吧? ~~~jsx // ?? 這不是 React Hooks API const nameKey = Symbol(); const surnameKey = Symbol(); const widthKey = Symbol(); function Form() { // 我們傳幾種state key給useState() const [name, setName] = useState(nameKey); const [surname, setSurname] = useState(surnameKey); const [width, setWidth] = useState(widthKey); // ... ~~~ 這個提案看上去對提取出來的`useWindowWidth`Hook 有效: ~~~jsx // ?? 這不是 React Hooks API function Form() { // ... const width = useWindowWidth(); // ... } /********************* * useWindowWidth.js * ********************/ const widthKey = Symbol(); function useWindowWidth() { const [width, setWidth] = useState(widthKey); // ... return width;} ~~~ 但如果嘗試提取出來的 input handling,它會失敗: ~~~jsx // ?? 這不是 React Hooks API function Form() { // ... const name = useFormInput(); const surname = useFormInput(); // ... return ( <> <input {...name} /> <input {...surname} /> {/* ... */} </> ) } /******************* * useFormInput.js * ******************/ const valueKey = Symbol(); function useFormInput() { const [value, setValue] = useState(valueKey); return { value, onChange(e) { setValue(e.target.value); }, };} ~~~ (我承認`useFormInput()`Hook 不是特別好用,但你可以想象下它處理諸如驗證和 dirty state 標志之類,如[Formik](https://github.com/jaredpalmer/formik)。) 你能發現這個bug嗎? 我們調用`useFormInput()`兩次,但`useFormInput()`總是用同一個 key 調用`useState()`,就像這樣: ~~~jsx const [name, setName] = useState(valueKey); const [surname, setSurname] = useState(valueKey); ~~~ 我們再次發生了沖突。 實際中 Hooks 提案沒有這種問題,因為**每次*調用*`useState()`會獲得單獨的state**。依賴于固定順序調用使我們免于擔心命名沖突。 ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-4%EF%BC%9A%E9%92%BB%E7%9F%B3%E9%97%AE%E9%A2%98%E5%A4%9A%E5%B1%82%E7%BB%A7%E6%89%BF%E9%97%AE%E9%A2%98)缺陷 #4:鉆石問題(多層繼承問題) 從技術上來說這個和上一個缺陷相同,但它的臭名值得說說,甚至維基百科都有介紹。(有些時候還被稱為「致命的死亡鉆石」 —— cool!) 我們自己的 mixin 系統就[受到了傷害](https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html#mixins-cause-name-clashes)。 比如`useWindowWidth()`和`useNetworkStatus()`這兩個 custom hooks 可能要用像`useSubscription()`這樣的 custom hook,如下: ~~~jsx function StatusMessage() { const width = useWindowWidth(); const isOnline = useNetworkStatus(); return ( <> <p>Window width is {width}</p> <p>You are {isOnline ? 'online' : 'offline'}</p> </> ); } function useSubscription(subscribe, unsubscribe, getValue) { const [state, setState] = useState(getValue()); useEffect(() => { const handleChange = () => setState(getValue()); subscribe(handleChange); return () => unsubscribe(handleChange); }); return state; } function useWindowWidth() { const width = useSubscription( handler => window.addEventListener('resize', handler), handler => window.removeEventListener('resize', handler), () => window.innerWidth ); return width; } function useNetworkStatus() { const isOnline = useSubscription( handler => { window.addEventListener('online', handler); window.addEventListener('offline', handler); }, handler => { window.removeEventListener('online', handler); window.removeEventListener('offline', handler); }, () => navigator.onLine ); return isOnline; } ~~~ 這是一個真實可運行的示例。**custom hook 作者準備或停止使用另一個 custom hook 應該是要安全的,而不必擔心它是否已在鏈中某處「被用過了」**。 (作為反例,遺留的 React`createClass()`的 mixins 不允許你這樣做,有時你會有兩個 mixins,它們都是你想要的,但由于擴展了同一個 「base」 mixin,因此互不兼容。) 這是我們的 「鉆石」:?? ~~~text / useWindowWidth() \ / useState() ?? Clash Status useSubscription() \ useNetworkStatus() / \ useEffect() ?? Clash ~~~ 依賴于固定的順序調用很自然的解決了它: ~~~text / useState() ? #1. State / useWindowWidth() -> useSubscription() / \ useEffect() ? #2. Effect Status \ / useState() ? #3. State \ useNetworkStatus() -> useSubscription() \ useEffect() ? #4. Effect ~~~ 函數調用不會有「鉆石」問題,因為它們會形成樹狀結構。?? ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-5%EF%BC%9A%E5%A4%8D%E5%88%B6%E7%B2%98%E8%B4%B4%E7%9A%84%E4%B8%BB%E6%84%8F%E8%A2%AB%E6%89%93%E4%B9%B1)缺陷 #5:復制粘貼的主意被打亂 或許我們可以通過引入某種命名空間來挽救給 state 加「key」提議,有幾種不同的方法可以做到這一點。 一種方法是使用閉包隔離 state 的 key,這需要你在 「實例化」 custom hooks時給每個 hook 裹上一層 function: ~~~jsx /******************* * useFormInput.js * ******************/ function createUseFormInput() { // 每次實例化都唯一 const valueKey = Symbol(); return function useFormInput() { const [value, setValue] = useState(valueKey); return { value, onChange(e) { setValue(e.target.value); }, }; } } ~~~ 這種作法非常繁瑣,Hooks 的設計目標之一就是避免使用高階組件和 render props 的深層嵌套函數。在這里,我們不得不在使用*任何*custom hook 時進行「實例化」 —— 而且在組件主體中只能單次使用生產的函數,這比直接調用 Hooks 麻煩好多。 另外,你不得不操作兩次才能使組件用上 custom hook。一次在最頂層(或在編寫 custom hook 時的函數里頭),還有一次是最終的調用。這意味著即使一個很小的改動,你也得在頂層聲明和render函數間來回跳轉: ~~~jsx // ?? 這不是 React Hooks API const useNameFormInput = createUseFormInput();const useSurnameFormInput = createUseFormInput(); function Form() { // ... const name = useNameFormInput(); const surname = useNameFormInput(); // ... } ~~~ 你還需要非常精確的命名,總是需要考慮「兩層」命名 —— 像`createUseFormInput`這樣的工廠函數和`useNameFormInput`、`useSurnameFormInput`這樣的實例 Hooks。 如果你同時調用兩次相同的 custom hook 「實例」,你會發生state沖突。事實上,上面的代碼就是這種錯誤 —— 發現了嗎? 它應該為: ~~~jsx const name = useNameFormInput(); const surname = useSurnameFormInput(); // Not useNameFormInput! ~~~ 這些問題并非不可克服,但我認為它們會比遵守[Hooks規則](https://reactjs.org/docs/hooks-rules.html)的阻力大些。 重要的是,它們打破了復制粘貼的小算盤。在沒有封裝外層的情況下這種 custom hook 仍然可以使用,但它們只可以被調用一次(這在使用時會產生問題)。不幸的是,當一個API看起來可以正常運行,一旦你意識到在鏈的某個地方出現了沖突時,就不得不把所有定義好的東西包起來了。 ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-6%EF%BC%9A%E6%88%91%E4%BB%AC%E4%BB%8D%E7%84%B6%E9%9C%80%E8%A6%81%E4%B8%80%E4%B8%AA%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5%E5%B7%A5%E5%85%B7)缺陷 #6:我們仍然需要一個代碼檢查工具 還有另外一種使用密鑰state來避免沖突的方法,如果你知道,可能會真的很生氣,因為我不看好它,抱歉。 這個主意就是每次寫 custom hook 時*組合*一個密鑰,就像這樣: ~~~jsx // ?? 這不是 React Hooks API function Form() { // ... const name = useFormInput('name'); const surname = useFormInput('surname'); // ... return ( <> <input {...name} /> <input {...surname} /> {/* ... */} </> ) } function useFormInput(formInputKey) { const [value, setValue] = useState('useFormInput(' + formInputKey + ').value'); return { value, onChange(e) { setValue(e.target.value); }, }; } ~~~ 和其他替代提議比,我最不喜歡這個,我覺得它沒有什么價值。 一個 Hook 經過多次調用或者與其他 Hook 沖突之后,代碼可能*意外產出*非唯一或合成無效密鑰進行傳遞。更糟糕的是,如果它是在某些條件下發生的(我們會試圖 「修復」 它對吧?),可能在一段時間后才發生沖突。 我們想提醒大家,記住所有通過密鑰來標記的 custom hooks 都很脆弱,它們不僅增加了運行時的工作量(別忘了它們要轉成*密鑰*),而且會漸漸增大 bundle 大小。**但如果說我們非要提醒一個問題,是哪個問題呢**? 如果非要在條件判斷里聲明 state 和 effects,這種方法可能是有作用的,但按過去經驗來說,我發現它令人困惑。事實上,我不記得有人會在條件判斷里定義`this.state`或者`componentMount`的。 這段代碼到底意味著什么? ~~~jsx // ?? 這不是 React Hooks API function Counter(props) { if (props.isActive) { const [count, setCount] = useState('count'); return ( <p onClick={() => setCount(count + 1)}> {count} </p>; ); } return null; } ~~~ 當`props.isActive`為`false`時`count`是否被保留?或者由于`useState('count')`沒有被調用而重置`count`? 如果條件為保留 state,effect 又會發生什么? ~~~jsx // ?? 這不是 React Hooks API function Counter(props) { if (props.isActive) { const [count, setCount] = useState('count'); useEffect(() => { const id = setInterval(() => setCount(c => c + 1), 1000); return () => clearInterval(id); }, []); return ( <p onClick={() => setCount(count + 1)}> {count} </p>; ); } return null; } ~~~ 無疑它不會在`props.isActive`第一次是`true`*之前*運行,但一旦變成`true`,它會停止運行嗎?當`props.isActive`轉變為`false`時 interval 會重置嗎?如果是這樣,effect 與 state(我們說不重置時) 的行為不同令人困惑。如果 effect 繼續運行,那么 effect 外層的`if`不再控制 effect,這也令人感到困惑,我們不是說我們想要基于條件控制的 effects 嗎? 如果在渲染期間我們沒有「使用」 state 但 它卻被重置,如果有多個`if`分支包含`useState('count')`但只有其中一個會在給定時間里運行,會發生什么?這是有效的代碼嗎?如果我們的核心思想是 「以密鑰分布」,那為什么要 「丟棄」 它?開發人員是否希望在這之后從組件中提前`return`以重置所有 state 呢? 其實如果我們真的需要重置state,我們可以通過提取組件使其明確: ~~~jsx function Counter(props) { if (props.isActive) { // 清晰地知道它有自己的 state return <TickingCounter />; } return null; } ~~~ 無論如何這可能成為是解決這些困惑問題的「最佳實踐」,所以不管你選擇哪種方式去解釋,我覺得條件里*聲明*state 和 effect 的語義怎樣都很怪異,你可能會不知不覺的感受到。 如果還要提醒的是 —— 正確地組合密鑰的需求會變成「負擔」,它并沒有給我們帶來任何想要的。但是,放棄這個需求(并回到最初的提案)確實給我們帶來了一些東西,它使組件代碼能夠安全地復制粘貼到一個 custom hook 中,且不需要命名空間,減小 bundle 大小及輕微的效率提升(不需要Map查找)。 慢慢理解。 ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-7%EF%BC%9Ahooks-%E4%B9%8B%E9%97%B4%E6%97%A0%E6%B3%95%E4%BC%A0%E5%80%BC)缺陷 #7:Hooks 之間無法傳值 Hooks 有個最好的功能就是可以在它們之間傳值。 以下是一個選擇信息收件人的模擬示例,它顯示了當前選擇的好友是否在線: ~~~jsx const friendList = [ { id: 1, name: 'Phoebe' }, { id: 2, name: 'Rachel' }, { id: 3, name: 'Ross' }, ]; function ChatRecipientPicker() { const [recipientID, setRecipientID] = useState(1); const isRecipientOnline = useFriendStatus(recipientID); return ( <> <Circle color={isRecipientOnline ? 'green' : 'red'} /> <select value={recipientID} onChange={e => setRecipientID(Number(e.target.value))} > {friendList.map(friend => ( <option key={friend.id} value={friend.id}> {friend.name} </option> ))} </select> </> ); } function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); const handleStatusChange = (status) => setIsOnline(status.isOnline); useEffect(() => { ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; } ~~~ 當改變收件人時,`useFriendStatus`Hook 就會退訂上一個好友的狀態,訂閱接下來的這個。 這是可行的,因為我們可以將`useState()`Hook 返回的值傳給`useFriendStatus()`Hook: ~~~jsx const [recipientID, setRecipientID] = useState(1); const isRecipientOnline = useFriendStatus(recipientID); ~~~ Hooks之間傳值非常有用。例如:[React Spring](https://medium.com/@drcmda/hooks-in-react-spring-a-tutorial-c6c436ad7ee4)可以創建一個尾隨動畫,其中多個值彼此「跟隨」: ~~~jsx const [{ pos1 }, set] = useSpring({ pos1: [0, 0], config: fast }); const [{ pos2 }] = useSpring({ pos2: pos1, config: slow }); const [{ pos3 }] = useSpring({ pos3: pos2, config: slow }); ~~~ (這是[demo](https://codesandbox.io/s/ppxnl191zx)。) 在Hook初始化時添加默認參數或者將Hook寫在裝飾器表單中的提議,很難實現這種情況的邏輯。 如果不在函數體內調用 Hooks,就不可以輕松地在它們之間傳值了。你可以改變這些值結構,讓它們不需要在多層組件之間傳遞,也可以用`useMemo`來存儲計算結果。但你也無法在 effects 中引用這些值,因為它們無法在閉包中被獲取到。有些方法可以通過某些約定來解決這些問題,但它們需要你在心里「核算」輸入和輸出,這違背了 React 直接了當的風格。 在 Hooks 之間傳值是我們提案的核心,Render props 模式在沒有 Hooks 時是你最先能想到的,但像[Component Component](https://ui.reach.tech/component-component)這樣的庫,是無法適用于你遇到的所有場景的,它由于「錯誤的層次結構」存在大量的語法干擾。Hooks 用扁平化層次結構來實現傳值 —— 且函數調用是最簡單的傳值方式。 ### [](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/#%E7%BC%BA%E9%99%B7-8%EF%BC%9A%E6%AD%A5%E9%AA%A4%E7%B9%81%E7%90%90)缺陷 #8:步驟繁瑣 有許多提議處于這種范疇里。他們盡可能的想讓React擺脫對 Hooks 的依賴感,大多數方法是這么做的:讓`this`擁有內置 Hooks,使它們變成額外的參數在React中無處不在,等等等。 我覺得[Sebastian的回答](https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884)比我的描述,更能說服這種方式,我建議你去了解下「注入模型」。 我只想說這和程序員傾向于用`try`/`catch`捕獲方法中的錯誤代碼是一樣的道理,同樣對比 AMD由我們自己傳入`require`的「顯示」聲明,我們更喜歡`import`(或者 CommonJS`require`) 的 ES模塊。 ~~~jsx // 有誰想念 AMD? define(['require', 'dependency1', 'dependency2'], function (require) { var dependency1 = require('dependency1'), var dependency2 = require('dependency2'); return function () {}; }); ~~~ 是的,AMD 可能更「誠實」 的陳述了在瀏覽器環境中模塊不是同步加載的,但當你知道了這個后,寫`define`三明治 就變成做無用功了。 `try`/`catch`、`require`和 React Context API都是我們更喜歡「環境」式體驗,多于直接聲明使用的真實例子(即使通常我們更喜歡直爽風格),我覺得 Hooks 也屬于這種。 這類似于當我們聲明組件時,就像從`React`抓個`Component`過來。如果我們用工廠的方式導出每個組件,可能我們的代碼會更解耦: ~~~jsx function createModal(React) { return class Modal extends React.Component { // ... }; } ~~~ 但在實際中,這最后會變得多此一舉而令人厭煩。當我們真的想以某種方式抓React時,我們應該在模塊系統層面上實現。 ## 摘自 [ 為什么順序調用對 React Hooks 很重要](https://overreacted.io/zh-hans/why-do-hooks-rely-on-call-order/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看