-
-
Save Kelin2025/e6ed7b8678c80cd9f5e43947aba96f87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CAUTION | |
// - Avoid dynamic factories calls | |
// - Generic factories are not supported in `useModel`and `modelView` components | |
'use client' | |
import { createFactory, invoke } from '@withease/factories' | |
import { Context, createContext, FC, Provider, useContext } from 'react' | |
const contexts = new Map< | |
ReturnType<typeof createFactory>, | |
Context<ReturnType<typeof invoke<ReturnType<typeof createFactory>>>> | |
>() | |
export const createModelProvider = <T extends (props: any) => any>(factory: T) => { | |
contexts.set(factory, createContext(null)) | |
return contexts.get(factory)!.Provider as Provider<ReturnType<typeof invoke<T>>> | |
} | |
export const useModel = <T extends (props: any) => any>(factory: T) => { | |
const model = useContext(contexts.get(factory)!) | |
if (!model) { | |
throw new Error('No model found') | |
} | |
return model as ReturnType<T> | |
} | |
/** | |
* HOC that wraps your `View` into model `Provider`. Also adds `model` prop that will be passed into `Provider` | |
* @param factory Factory that will be passed through Context | |
* @param View Root component that will be wrapped into Context | |
* @returns Wrapped component | |
*/ | |
export const modelView = <T extends (props: any) => any, Props extends {} = {}>( | |
factory: T, | |
View: FC<Props & { model: ReturnType<typeof invoke<T, Parameters<T>[0]>> }>, | |
) => { | |
const Provider = createModelProvider(factory) | |
const Render = (props: Props & { model: ReturnType<typeof invoke<T, Parameters<T>[0]>> }) => { | |
return ( | |
<Provider value={props.model}> | |
<View {...props} /> | |
</Provider> | |
) | |
} | |
// `as` is used for a better "Go To Definition" | |
return Render as typeof View | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment