diff --git a/src/CroctProvider.test.tsx b/src/CroctProvider.test.tsx
index 13edc404..3c6b02e5 100644
--- a/src/CroctProvider.test.tsx
+++ b/src/CroctProvider.test.tsx
@@ -22,6 +22,8 @@ describe('', () => {
afterEach(() => {
// eslint-disable-next-line no-console -- Needed to restore the original console.error.
console.error = consoleError;
+
+ jest.clearAllMocks();
});
it('should fail if nested', () => {
@@ -68,7 +70,6 @@ describe('', () => {
);
expect(callback).toHaveBeenCalledTimes(1);
- expect(callback).toHaveBeenCalledWith({plug: croct});
expect(croct.plug).toHaveBeenCalledTimes(2);
expect(croct.plug).toHaveBeenNthCalledWith(1, options);
@@ -83,6 +84,39 @@ describe('', () => {
expect(croct.unplug).toHaveBeenCalled();
});
+ it('should allow to plug after unmount', () => {
+ const options: CroctProviderProps = {
+ appId: '00000000-0000-0000-0000-000000000000',
+ debug: true,
+ track: true,
+ };
+
+ let plug: Plug|undefined;
+
+ const callback = jest.fn((context: {plug: Plug}|null) => {
+ plug = context?.plug;
+
+ return 'foo';
+ });
+
+ render(
+
+ {callback}
+ ,
+ );
+
+ const appId = '11111111-1111-1111-1111-111111111111';
+
+ plug?.plug({appId: appId});
+
+ expect(croct.plug).toHaveBeenCalledTimes(2);
+
+ expect(croct.plug).toHaveBeenLastCalledWith({
+ ...options,
+ appId: appId,
+ });
+ });
+
it('should ignore errors on unmount', () => {
jest.mocked(croct.unplug).mockRejectedValue(new Error('foo'));
diff --git a/src/CroctProvider.tsx b/src/CroctProvider.tsx
index dc0f33a2..b6c923b7 100644
--- a/src/CroctProvider.tsx
+++ b/src/CroctProvider.tsx
@@ -3,6 +3,7 @@
import {
createContext,
FunctionComponent,
+ MutableRefObject,
PropsWithChildren,
ReactElement,
useContext,
@@ -18,10 +19,18 @@ export type CroctProviderProps = PropsWithChildren(null);
CroctContext.displayName = 'CroctContext';
+function useLiveRef(value: T): MutableRefObject {
+ const ref = useRef(value);
+
+ ref.current = value;
+
+ return ref;
+}
+
export const CroctProvider: FunctionComponent = (props): ReactElement => {
const {children, ...configuration} = props;
const parent = useContext(CroctContext);
- const initialConfiguration = useRef(configuration);
+ const baseConfiguration = useLiveRef(configuration);
if (parent !== null) {
throw new Error(
@@ -34,18 +43,28 @@ export const CroctProvider: FunctionComponent = (props): Rea
() => ({
get plug(): Plug {
if (!croct.initialized) {
- croct.plug(initialConfiguration.current);
+ croct.plug(baseConfiguration.current);
}
- return croct;
+ return new Proxy(croct, {
+ get: function getProperty(target, property: keyof Plug): any {
+ if (property === 'plug') {
+ return (options: Configuration): void => {
+ croct.plug({...baseConfiguration.current, ...options});
+ };
+ }
+
+ return target.plug[property];
+ },
+ });
},
}),
- [],
+ [baseConfiguration],
);
useEffect(
() => {
- croct.plug(initialConfiguration.current);
+ croct.plug(baseConfiguration.current);
return () => {
croct.unplug().catch(() => {
@@ -53,7 +72,7 @@ export const CroctProvider: FunctionComponent = (props): Rea
});
};
},
- [],
+ [baseConfiguration],
);
return (