在React Native中使用Inversify时如何避免服务定位器模式?
在React Native函数式组件中用InversifyJS实现Props式依赖注入
你遇到的问题本质是:Inversify的@lazyInject这类装饰器仅支持类组件,函数组件无法直接使用装饰器语法,而useInjection属于你想避免的服务定位器模式。下面是两种可行方案,实现通过props注入依赖的目标:
方案一:使用高阶组件(HOC)注入依赖
这是最直接符合你需求的方式——通过HOC将依赖从Inversify容器中取出,作为props传递给函数组件。
1. 定义接受依赖的组件
先调整组件的Props类型,把需要注入的服务明确加入Props:
import { Dispatch } from 'redux'; import { INavigationService } from './path-to-your-services'; // 组件原有基础Props interface ISettingsBaseProps { navigation?: any; } // 需要注入的服务Props interface ISettingsInjectedProps { navigationService: INavigationService; } // 合并后的完整Props类型 type ISettingsProps = ISettingsBaseProps & ISettingsInjectedProps & { dispatch: Dispatch }; const Settings = ({ dispatch, navigationService, ...baseProps }: ISettingsProps) => { return ( <AuthenticatedView {...{ ...baseProps, style: { justifyContent: 'flex-start', marginTop: '70%', alignItems: 'center' } }} > <Text>Settings!</Text> <Button onPress={() => navigationService.navigate(baseProps, "Trade", dispatch)} title="Trade" /> </AuthenticatedView> ); };
2. 创建注入用的HOC
编写一个高阶组件,从Inversify容器中解析服务,传递给目标组件:
import { container } from './path-to-your-inversify-container'; // 导入你的Inversify容器 import { TYPES } from './path-to-your-types'; // 通用注入HOC,可复用给其他组件 const withInjectedNavigationService = <P extends object>( Component: React.ComponentType<P & ISettingsInjectedProps> ) => { return (props: P) => { // 从容器中解析服务 const navigationService = container.resolve<INavigationService>(TYPES.NavigationService); // 将服务作为props传递给组件 return <Component {...props} navigationService={navigationService} />; }; };
3. 导出包裹后的组件
// 外部使用该组件时,无需手动传递navigationService export default withInjectedNavigationService(Settings);
方案二:自定义注入Hook(进阶)
如果你更倾向于Hook风格,但又想尽量弱化服务定位器的感知,可以封装一个自定义Hook,不过本质还是基于容器解析:
import { container } from './path-to-your-inversify-container'; import { TYPES } from './path-to-your-types'; import { INavigationService } from './path-to-your-services'; // 自定义Hook,封装依赖解析逻辑 const useNavigationService = (): INavigationService => { return container.resolve<INavigationService>(TYPES.NavigationService); }; // 在组件中使用 const Settings = (props: ISettingsBaseProps) => { const dispatch = useDispatch(); const navigationService = useNavigationService(); // 替代useInjection return ( // ... 组件内容和之前一致 ); }; export default Settings;
注:这个方案虽然用了Hook,但本质还是服务定位器模式,只是做了封装。如果严格要求通过props注入,方案一更符合你的需求。
为什么@lazyInject不可行?
Inversify的装饰器(包括@lazyInject)是基于类的装饰器语法,只能用于类或类的成员(比如类组件的属性)。函数组件是普通JavaScript/TypeScript函数,不支持类装饰器语法,所以会报Decorators are not valid here错误,这个方向无法适配函数组件。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

