diff --git a/packages/reactant/src/createApp.tsx b/packages/reactant/src/createApp.tsx index cece32318..36a45d488 100644 --- a/packages/reactant/src/createApp.tsx +++ b/packages/reactant/src/createApp.tsx @@ -10,9 +10,12 @@ import { Loader, PluginHooks, ModulesMap, + Container, } from 'reactant-module'; import { Config, App, Renderer } from './interfaces'; +export const ContainerContext = React.createContext(null); + /** * ## Description * @@ -157,9 +160,13 @@ function createApp>({ InstanceElement ); const element = withoutReducers ? ( - RootElement + + {RootElement} + ) : ( - {RootElement} + + {RootElement} + ); return render( devOptions?.strict ? {element} : element, diff --git a/packages/reactant/src/hooks/useConnector.ts b/packages/reactant/src/hooks/useConnector.ts index f42d012c1..4ba7fb3e8 100644 --- a/packages/reactant/src/hooks/useConnector.ts +++ b/packages/reactant/src/hooks/useConnector.ts @@ -1,6 +1,8 @@ /* eslint-disable no-console */ +import { useContext } from 'react'; import { useSelector, useStore } from 'react-redux'; -import { areShallowEqualWithObject } from 'reactant-module'; +import { areShallowEqualWithObject, Container } from 'reactant-module'; +import { ContainerContext } from '../createApp'; import { ShallowEqual } from '../interfaces'; /** @@ -44,12 +46,13 @@ import { ShallowEqual } from '../interfaces'; * ``` */ export function useConnector( - selector: () => T, + selector: (container: Container) => T, shallowEqual?: ShallowEqual ) { try { + const container = useContext(ContainerContext); return useSelector( - selector, + () => selector(container!), shallowEqual || areShallowEqualWithObject ) as T; } catch (e) { diff --git a/packages/reactant/test/useConnector.test.tsx b/packages/reactant/test/useConnector.test.tsx index 420031075..0ca3d142d 100644 --- a/packages/reactant/test/useConnector.test.tsx +++ b/packages/reactant/test/useConnector.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable no-shadow */ import React, { FC } from 'react'; import { unmountComponentAtNode, render } from 'reactant-web'; // eslint-disable-next-line import/no-extraneous-dependencies @@ -201,4 +202,39 @@ describe('useConnector', () => { }); }).toThrow(); }); + + test('selector with container getter', () => { + const renderFn = jest.fn(); + + @injectable() + class FooView extends ViewModule { + @state + key: string | null = null; + + @action + setValue(value: string) { + this.key = value; + } + + component() { + const value = useConnector((container) => container.get(FooView).key); + renderFn(value); + return null; + } + } + + const app = createApp({ + modules: [], + main: FooView, + render, + }); + expect(renderFn).toBeCalledTimes(0); + act(() => { + app.bootstrap(container); + }); + expect(renderFn).toBeCalledTimes(1); + app.instance.setValue('str'); + expect(renderFn).toBeCalledTimes(2); + expect(renderFn.mock.calls).toEqual([[null], ['str']]); + }); });