不必照顧上下文類型的技巧很簡單!
如果您使用上下文 API,那麼一個問題就是其類型的照顧。
另一個是必須使用多個導入才能在需要時使用它。
透過這個範例,我們解決了這兩個問題,並使 React Context API 的使用變得快速、簡單。
複製、貼上,然後只需將所有「範例」替換為您需要命名的內容即可。
(之後會有完整註解的版本。)
import { createContext, useCallback, useContext, useDeferredValue, useMemo, useState, } from 'react'; function useContextValue(init: number = 0) { const [state, setState] = useState(init); const doubleValue = state * 2; const defferedStringValue = useDeferredValue(state.toString()); const reset = useCallback(() => { setState(init); }, []); const value = useMemo( () => ({ state, doubleValue, defferedStringValue, reset, }), [ state, doubleValue, defferedStringValue, reset, ], ); return value; } type ExampleContext = ReturnType; const Context = createContext (null!); Context.displayName = 'ExampleContext'; export function ExampleContextProvider({ children, initValue = 0, }: { children: React.ReactNode; initValue?: number; }) { const value = useContextValue(initValue); return {children} ; } export function useExample() { const value = useContext(Context); if (!value) { throw new Error('useExample must be used within a ExampleContextProvider'); } return value; }
import { createContext, useCallback, useContext, useDeferredValue, useMemo, useState, } from 'react'; /** * We create a custom hook that will have everything * that would usually be in the context main function * * this way, we can use the value it returns to infer the * type of the context */ function useContextValue(init: number = 0) { // do whatever you want inside const [state, setState] = useState(init); const doubleValue = state * 2; const defferedStringValue = useDeferredValue(state.toString()); // remember to memoize functions const reset = useCallback(() => { setState(init); }, []); // and also memoize the final value const value = useMemo( () => ({ state, doubleValue, defferedStringValue, reset, }), [ state, doubleValue, defferedStringValue, reset, ], ); return value; } /** * Since we can infer from the hook, * no need to create the context type by hand */ type ExampleContext = ReturnType; const Context = createContext (null!); Context.displayName = 'ExampleContext'; export function ExampleContextProvider({ children, /** * this is optional, but it's always a good to remember * that the context is still a react component * and can receive values other than just the children */ initValue = 0, }: { children: React.ReactNode; initValue?: number; }) { const value = useContextValue(initValue); return {children} ; } /** * We also export a hook that will use the context * * this way, we can use it in other components * by importing just this one hook */ export function useExample() { const value = useContext(Context); /** * this will throw an error if the context * is not used within the provider * * this also avoid the context being "undefined" */ if (!value) { throw new Error('useExample must be used within a ExampleProvider'); } return value; }
就是這樣。 Context API 比應有的更簡單、更精細,但對於需要使用它的情況來說,它是一個強大的工具。
請記住,React Context API 不是 Redux(或其他狀態管理器),您不應該將整個應用程式狀態放入其中。
嗯,可以,但可能會導致不必要的問題。
這是在 React
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3