我正在尝试在使用函数式组件方法的 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;
但是我收到以下错误:
装饰器在这里无效
但是,这似乎是朝着正确方向迈出的一步(如果我能让它发挥作用)。
这个问题的答案似乎是应该避免自定义依赖注入/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 的最简洁的方法。