import React, { PropsWithChildren, useRef } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { ObjectGraph } from '../../graph/ObjectGraph'; import PropsInjector from './PropsInjector'; import useGraph from './useGraph'; import Sentinel from './Sentinel'; import { Constructable } from '../../types'; import { genericMemo, isMemoizedComponent } from '../../utils/React'; import { GraphContext } from './graphContext'; import { useInjectionToken } from './useInjectionToken'; export default class ComponentInjector { inject

( Target: React.FunctionComponent

, keyOrGraph: string | Constructable, ): React.FunctionComponent> { const Wrapped = this.wrapComponent(Target, keyOrGraph); hoistNonReactStatics(Wrapped as any, Target as any); return Wrapped; } private wrapComponent

( InjectionCandidate: React.FunctionComponent

, keyOrGraph: string | Constructable, ): React.FunctionComponent> { const isMemoized = isMemoizedComponent(InjectionCandidate); const Target = isMemoized ? InjectionCandidate.type : InjectionCandidate; const compare = isMemoized ? InjectionCandidate.compare : undefined; return genericMemo((passedProps: P) => { const injectionToken = useInjectionToken(keyOrGraph); const containerRef = useRef(null); const graph = useGraph

(keyOrGraph, Target, passedProps, injectionToken, containerRef); const proxiedProps = new PropsInjector(graph).inject(passedProps); return ( {graph.inactiveBehavior === 'retain' && } {Target(proxiedProps as unknown as PropsWithChildren

) as React.ReactNode} ); }, compare); } }