Dependency Injection architectural pattern in a React application

Transcript of Sergei Nesterov's report from the FrontendLive 2020 conference .





! , . , , , , , React . Dependency Injection IoC-. : , .





- . , , - -.





Dependency Injection React-. , , . , Dependency Injection , . 





:





Frontend + DI โ‰  โ™ฅ







- , Dependency Injection, , , , . Dependency Injection -, , , . , , , , .





, Dependency Injection. , Angular Nest.js ( NodeJS). Angular Dependency Injection , React- React .





โ€” : 





Frontend + DI = โ™ฅ



 





, React- Dependency Injection. , .





. React MobX. - , React- . , . 





, , , . , , , , , . , , . :





: , , . , 30 . , , , - . , โ€” , . 





, , โ€” . .





. : . , , , , . , , . 





. React 16.2 16.3. , API, . - , ( ), โ€” props hell. 





- , , , . - , , . , . , . 





, Dependency Injection. โ€” - , SOLID.





SOLID





  • .





  • /.





  • .





  • .





  • .





โ€” . ?





  • . .





  • . .





, , : 





: ( Juicer) ( Apple). Juicer Apple. ? , : Juicer Apple. :





  • Apple. 





  • . Juicer, , Apple.





  • . ยซยป ยซยป, , , . ยซยป.





, , IFruit , ยซยป , - . 





Apple โ€” โ€” , . :





Juicer, -, , - IFruit. Apple Juicer. , .





, ! , , - , . 





, , . 





Dependency Injection. , : 





  • Constructor injection.





  • Property Injection.





  • Setter Injection.





Constructor injection. , . , : , - . , , :





Property Injection. . property . , , -, โ€” , , : 





-, , . -, , , - . - IoC-, , .





Setter Injection. , Property Injection, property , , . . . , Property Injection, ( ), :





:

  • Constructor Injection โ€” . , .





  • Property Injection โ€” .





  • Setter Injection โ€” . Inversion of Control-.





IoC-, . 





. IoC- โ€” , , , : , , , , .





. IoC- โ€” , โ€” . , , . 





React

react-simple-di, react-ioc, typescript-ioc, inversifyJS.





inversifyJS, . React. , Dependency Injection Angular, inversifyJS.





devtools. , โ€” . , - , inversifyJS , :





. Juicer, Apple. inversifyJS, , injectable-, .





inject- Apple, . โ€” inversifyJS, , .





: ยซ , , !ยป , . :





? Apple IFruit. @inject Apple.





? IFruit is not defined โ€” ReferenceError. 





? , , runtime TypeScript โ€” JavaScript . , , InversifyJS , .





, ? , โ€” :





, FruitKey. โ€” , Apple . , Dependency Injection .





Reflect-metadata

Reflect-metadata โ€” , ( ) . , :





Juicer, โ€” injectable- inject-. , - inversify- , Juicer . , reflect-metadata Juice.





console.log(Reflect.getMetadataKeys) . :





  • design:paramtypes;





  • inversify:tagged;





  • inversify:paramtypes.





, , inversifyJS , . inversify:tagged:





console.log(Reflect.getMetadata) inversify:tagged , Juicer , FruitKey. inversifyJS : , . 





Dependency Injection+React

โ€” Dependency Injection React-. , React , React . , . , , . , . .





import React from 'react';
import { interfaces } from 'inversify';
 
const context = React.createContext<interfaces.Container | null>(null);
 
export default context;
      
      



. , , React. : , React.createContext null. inversifyJS , .





, ? DiProvider โ€” -, . , : (children) React-, :





type Props = {
   container: interfaces.Container;
   children: ReactNode;
};
 
export function DiProvider({ container, children }: Props) {
   return <Context.Provider value={container}>{children}</Context.Provider>;
}
      
      



High-Order-, . High-Order-, , , withProvider, โ€” , :





export function withProvider<P, C>(
   component: JSXElementConstructor<P> & C,
   container: interfaces.Container
) {
 
   class ProviderWrap extends Component<Props> {
       public static contextType = Context;
       public static displayName = `diProvider(${getDisplayName(component)})`;
 
       public constructor(props: Props, context?: interfaces.Container) {
           super(props);
 
           this.context = context;
 
           if (this.context) {
               container.parent = this.context;
           }
       }
 
       public render() {
           const WrappedComponent = component;
 
           return (
               <DiProvider container={container}>
                   <WrappedComponent {...(this.props as any)} />
               </DiProvider>
           );
       }
   }
 
   return ProviderWrap as ComponentClass<Props>;
}
      
      



. Typescript, , High-Order- , . , DiProvider , .





, DI-. , parent- . , , .





, . High-Order-, , . , , โ€” Dependence-.





Dependence- , . . , inversify, binding ( ), tagged binding โ€” . 





, , , TypeScript , . , , . 





inject. , DI-, resolve, . , . 





, , High-Order- React, . 





Next.js, . Next.js : npm install, npm run dev โ€” . pages- HOC withProvider , .





, HOC diInject, , - . 





: ListModel , inSingletonScope, , get- . Props , booksListModel , . inversifyJS React- , , .





, Dependency Injection, โ€” , inversifyJS.





, :





SPA- . React Router . , : fetch-, - fetch โ€” , . 





, , , . , 1, 2.





, , . , .





, โ€” , , -, , -, js, . 





:





, . : CommentService, CommentModel .





, inversifyJS Container Module, , . , . , .





inversifyJS, . โ€” tagged bindings. ? , :





, . inversifyJS tagged , FruitKey ( ) . โ€” , FruitKey โ€” , , โ€” , โ€” . , whenTargetTagged.





, , โ€” named bindings:





, , , โ€” Store, . , , JuicerKey c AppleJuicer. named inversifyJS. 





whenAnyAncestorNamed , AppleJuicer, โ€” OrangeJuicer. 





, Juicer FruitKey , , , โ€” . Store .





Dependency Injection+React

DI React? , , โ€” , . , , , runtime JavaScript, :





, , Store StoreKey. Store , , , TypeScript , - .





- - , , .





container.bind<Store>("StoreKey").to(Store);
      
      



, . 





 

, . Dependency Injection, . . .





. : โ€” playground , inversifyJS NodeJS, โ€” React-. High-Order- React inversifyJS.








All Articles