在 React Native 中使用 inversify 时如何避免服务定位器模式?

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

我正在尝试在使用函数式组件方法的 React Native 应用程序中使用 InversifyJS。我已配置所有内容并按其应有的方式工作,但是,实现依赖项注入的唯一方法是使用服务定位器模式(我想避免的东西):

const Settings = (props: ISettingsProps) => {
    const dispatch = useDispatch();
    const navigationService = useInjection<INavigationService>(TYPES.NavigationService);

    return (
        <AuthenticatedView {...{ ...props, style: {justifyContent: 'flex-start', marginTop: '70%', alignItems:'center'}}}>
            <Text>Settings!</Text>
            <Button onPress={() => navigationService.navigate(props, "Trade", dispatch)} title="Trade" />
        </AuthenticatedView>
    )
}

export default Settings;

上面的代码使用了使用上述服务定位器定位的导航服务。

我想做的是使用

props
将服务注入到组件中,但是,我似乎不知道如何做到这一点。我查阅了几个教程,包括这个:

https://synergycodes.com/blog/dependency-injection-in-react-using-inversifyjs/

如果我使用

@lazyInject
,似乎有一种方法——但是,这种进行 DI 的方法似乎只在基于类的组件中受支持(我想坚持使用函数式,因为 React 自己推荐了这种特定的范例)。

我试过这个:

@lazyInject(TYPES.NavigationService) let navigationService: INavigationService;

但是我收到以下错误:

装饰器在这里无效

但是,这似乎是朝着正确方向迈出的一步(如果我能让它发挥作用)。

typescript react-native dependency-injection inversifyjs
1个回答
0
投票

这个问题的答案似乎是应该避免自定义依赖注入/IOC。至少,使用钩子时是这样的。我采取的方法是使用

createContext
钩子来注册和使用依赖项。

首先,我在自定义 AppContextWrapper 组件中注册依赖项。在本例中,我有两个依赖项:authService 和 navigationService

interface IAppContext {
    authService: IAuthService;
    navigationService: INavigationService;
}

const contextDependencies = {
    authService: new AuthService(),
    navigationService: new NavigationService()
}

export const AppContext = createContext<IAppContext | null>(null);

export default function AppContextWrapper(props: IApplicationProps) {
    return (
        <AppContext.Provider value={contextDependencies}>
            {props.children}
        </AppContext.Provider>
    );
}

然后用包装器包装主 App.tsx:

export default function App() {
  return (
    <AppContextWrapper>
      ...
    </AppContextWrapper>
  )
}

然后我可以调用上下文并通过在子组件中使用

useContext
来获取所需的类型。在这里,我在“设置”屏幕中使用导航服务:

const Settings = (props: ISettingsProps) => {
    const dispatch = useDispatch();
    const navigationService = useContext(AppContext)?.navigationService;
    return (
        <AuthenticatedView {...{ ...props, style: {justifyContent: 'flex-start', marginTop: '70%', alignItems:'center'}}}>
            <Text>Settings!</Text>
            <Button onPress={() => navigationService?.navigate(props, "Trade", dispatch)} title="Trade" />
        </AuthenticatedView>
    )
}

export default Settings;

这与服务定位器模式密切相关,但是,似乎没有办法解决这个问题。这似乎是通过现代 React 实现 DI 的最简洁的方法。

© www.soinside.com 2019 - 2024. All rights reserved.