不必照顾上下文类型的技巧很简单!
如果您使用上下文 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