如何为 React Context.Provider 提供多个实现?

问题描述 投票:0回答:0

我正在使用 nextjs 和 react

域:一个输入管理系统,其中文档可以直接与收件箱或任务相关联。取决于配置。

问题陈述: 根据环境变量,我想提供取决于不同提供商的不同收件箱:

//index.page.tsx
const InboxPage: NextPageWithLayout = () => {
    const {supportTasks} = useConfiguration()

    const taskInbox = () =>
        <InboxProvider>
            <TaskProvider>
                <DocumentsProvider>
                    <TaskInbox/>
                </DocumentsProvider>
            </TaskProvider>
        </InboxProvider>;

    const documentInbox = () =>
        <InboxProvider>
            <DocumentsProvider>
                <DocumentInbox/>
            </DocumentsProvider>
        </InboxProvider>;

    return (
        <>
            {supportTasks ? taskInbox() : documentInbox()}
        </>
    );
};

我想要** DocumentsProvider** 的两种不同实现,调用者不必担心系统当前运行的是哪种“配置”模式。呼叫者应该始终能够呼叫:

  const { documents, setSelectedDocuments, selectedDocuments } = useDocuments();
并根据 Provider 的实现(inboxDocument 或 taskDocument)接收文档。

我尝试使用以下通用 useDocuments.tsx 文件实现此目的,其中根据配置应注入两个可用实现的 contextValue:

//useDocuments.tsx
//imports omitted

export type DocumentContextProps = {
    //some methods and values
};

type Contexts = {
    inbox: DocumentContextProps;
    task: DocumentContextProps;
};

const DocumentsContext = React.createContext<DocumentContextProps | null>(null);

export const useDocuments = (): DocumentContextProps => {
    const documentsContext = useContext(DocumentsContext);
    if (!documentsContext) {
        throw new Error('useDocuments must be used within a DocumentsProvider');
    }
    return documentsContext;
};

const DocumentsProvider: React.FunctionComponent<PropsWithChildren> = ({children}) => {
    const {supportTasks} = useConfiguration();
    const contexts: Contexts = {
        inbox: useContext(InboxDocumentsContext),
        task: useContext(TaskDocumentsContext),
    };

    const contextValue = supportTasks ? contexts.task : contexts.inbox;

    return <DocumentsContext.Provider value={contextValue}>
        {children}
    </DocumentsContext.Provider>;
};

export default DocumentsProvider;

两个实现是:

// useInboxDocuments.tsx

export const TaskDocumentsContext = React.createContext<DocumentContextProps>(
    {
        //default values
    }
);

const TaskDocumentsProvider: React.FunctionComponent<PropsWithChildren> = ({ children }) => {

   //providing business-logic

    return (<TaskDocumentsContext.Provider value={{
        //values
    }}>{children}</TaskDocumentsContext.Provider>)
};

export default TaskDocumentsProvider;

和:

//useTaskDocuments.tsx

export const TaskDocumentsContext = React.createContext<DocumentContextProps>(
    {
        //default values
    }
);

const TaskDocumentsProvider: React.FunctionComponent<PropsWithChildren> = ({ children }) => {

    //providing business-logic


    return (<TaskDocumentsContext.Provider value={{
        // values
    }}>{children}</TaskDocumentsContext.Provider>)
};

export default TaskDocumentsProvider;

此实现失败,因为检查 useDocuments (useDocuments.tsx) 会抛出错误:

   if (!documentsContext) { throw new Error('useDocuments must be used within a DocumentsProvider'); }

我怎样才能将这两个提供者合二为一。请注意,两个提供程序都实现了完全相同的方法。

reactjs next.js react-hooks react-context
© www.soinside.com 2019 - 2024. All rights reserved.