【问题标题】:Create React Context that returns 2 Other Functions Through Context Provider创建通过 Context Provider 返回 2 个其他函数的 React Context
【发布时间】:2021-03-17 18:27:26
【问题描述】:

我对 ReactJS 和 TypeScript 比较陌生,可以使用一些帮助来创建一个允许我调用方法并意识到我可能有很多错误的反应组件。下面是我的代码。

import { SomeExternalPackage } from "@external";

interface MyServiceProviderProps { 
       isInternal: boolean; 
       isEnabled: boolean;
} 
    
export const MyServiceProvider: React.FC<MyProviderProps> = (serviceProperty: MyServiceProviderProps) => { 
       const reportImpressionAsync = (creative: string) => {
               if (serviceProperty.isEnabled) {
                       SomeExternalPackage?.reportImpressionAsync(creative);
               }
       } 

       const reportActionAsync = (creative: string, action: SomeExternalPackage.Action) => { 
                   if (serviceProperty.isInternal) {
                       SomeExternalPackage?.reportActionAsync(creative, action);
               }
       } 

       const MyServiceContext = React.createContext(''); // TODO: What do I pass in here?
       return ( 
               <MyServiceContext.Provider value={{
                       reportActionAsync: reportActionAsync,
                       reportImpressionAsync: reportImpressionAsync
                       }}>
                   {serviceProperty} // Is this right?
               </MyServiceContext.Provider> 
       );
};

这是我到目前为止的粗略想法。理想情况下,从页面组件中,我可以使用 .Consumer 来提供这两个函数,并且在页面内部我可以调用任何一个函数。

【问题讨论】:

  • 如果不进一步了解您要达到的目标,回答您的问题有点困难。我的印象是 Context 不是解决您问题的正确方法,使用自定义钩子或高阶组件可以更好地解决它。 isEnabledisInternal 属性从何而来?它们是您需要更改的东西还是来自某些静态配置?
  • 感谢您的评论!我要解决的问题是我想要一种通用的方法来通过上下文提供者从任何子组件包装器访问这两个函数。我想在创建包装页面组件的 MyServiceProvider 实例时可以提供 isEnabled 和 isInternal 。因此,此提供程序使用这两个成员参数包装的所有页面都可以访问这两个函数/参数。听起来好吗?很想听听你的想法:)
  • 对于不同的页面是否有不同的 MyServiceProvider 实例,或者在整个应用程序中是否相同?
  • 我很想知道这对答案有何影响。我认为现在整个应用程序都是一样的,但如果可以的话,我也很想听到对方的声音

标签: reactjs typescript react-context


【解决方案1】:

根据我的理解,这样的事情应该可以工作:

import React from 'react'

// faking SomeExternalPackage
type Action = unknown

const SomeExternalPackage = {
    reportActionAsync: (creative: string, action: Action) => {},
    reportImpressionAsync: (creative: string) => {}
}

interface MyServiceProviderProps {
    children: React.ReactNode;
     isInternal: boolean; 
     isEnabled: boolean;
}

export const MyServiceContext = React.createContext({
    reportActionAsync: (creative: string, action: Action) => {},
    reportImpressionAsync: (creative: string) => {}
})
    
export const MyServiceProvider: React.FC<MyServiceProviderProps> = (props: MyServiceProviderProps) => { 
    const reportImpressionAsync = (creative: string) => {
        if (props.isEnabled) {
            SomeExternalPackage.reportImpressionAsync(creative);
        }
    } 

    const reportActionAsync = (creative: string, action: Action) => { 
        if (props.isInternal) {
            SomeExternalPackage.reportActionAsync(creative, action);
        }
    } 

    return ( 
        <MyServiceContext.Provider value={{
            reportActionAsync: reportActionAsync,
            reportImpressionAsync: reportImpressionAsync
        }}>
        {props.children}
        </MyServiceContext.Provider> 
    );
};

然后,您可以使用此 MyServiceProvider 组件并将其呈现在应用程序顶层附近的某个位置(例如在您的 App 组件中),以便它包装所有其他组件并提供这些功能。

要在另一个组件中使用这些函数,您可以执行以下操作:

import { MyServiceContext } from 'path/to/MyServiceContext'

const MyComponent = () => {
  const { reportActionAsync, reportImpressionAsync } = React.useContext(MyServiceContext)
}

【讨论】:

  • 谢谢!!!这太棒了,真的帮助我前进
猜你喜欢
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 2021-09-26
  • 2021-08-08
  • 1970-01-01
相关资源
最近更新 更多