Skip to content

Commit

Permalink
Merge createActorContext options with Provider options (#4695)
Browse files Browse the repository at this point in the history
* Merge createActorContext options with provided options

* Changeset

* Update packages/xstate-react/src/createActorContext.ts

Co-authored-by: Mateusz Burzyński <[email protected]>

* Improve test

* Oops

---------

Co-authored-by: Mateusz Burzyński <[email protected]>
  • Loading branch information
davidkpiano and Andarist authored Jan 23, 2024
1 parent 43fc63b commit 52900a0
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 4 deletions.
18 changes: 18 additions & 0 deletions .changeset/honest-spoons-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@xstate/react': patch
---

Options in `createActorContext` are now properly merged with provider options. Previously, provider options replaced the actor options.

```tsx
const { inspect } = createBrowserInspector();

const SomeContext = createActorContext(someMachine, { inspect });

// ...
// Options are now merged:
// { inspect: inspect, input: 10 }
<SomeContext.Provider options={{ input: 10 }}>
{/* ... */}
</SomeContext.Provider>;
```
9 changes: 6 additions & 3 deletions packages/xstate-react/src/createActorContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useSelector as useSelectorUnbound } from './useSelector';

export function createActorContext<TLogic extends AnyActorLogic>(
actorLogic: TLogic,
interpreterOptions?: ActorOptions<TLogic>
actorOptions?: ActorOptions<TLogic>
): {
useSelector: <T>(
selector: (snapshot: SnapshotFrom<TLogic>) => T,
Expand All @@ -30,7 +30,7 @@ export function createActorContext<TLogic extends AnyActorLogic>(
children,
logic: providedLogic = actorLogic,
machine,
options: providedOptions = interpreterOptions
options: providedOptions
}: {
children: React.ReactNode;
logic: TLogic;
Expand All @@ -46,7 +46,10 @@ export function createActorContext<TLogic extends AnyActorLogic>(
);
}

const actor = useActorRef(providedLogic, providedOptions);
const actor = useActorRef(providedLogic, {
...actorOptions,
...providedOptions
});

return React.createElement(OriginalProvider, {
value: actor,
Expand Down
51 changes: 50 additions & 1 deletion packages/xstate-react/test/createActorContext.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { createMachine, assign, fromPromise, Snapshot } from 'xstate';
import {
createMachine,
assign,
fromPromise,
Snapshot,
InspectionEvent
} from 'xstate';
import { fireEvent, screen, render, waitFor } from '@testing-library/react';
import { useSelector, createActorContext, shallowEqual } from '../src';

Expand Down Expand Up @@ -470,4 +476,47 @@ describe('createActorContext', () => {

expect(screen.getByTestId('value').textContent).toBe('84');
});

it('should merge createActorContext options with options passed to the provider', () => {
const events: InspectionEvent[] = [];
const SomeContext = createActorContext(
createMachine({
types: {
context: {} as { count: number },
input: {} as number
},
context: ({ input }) => ({ count: input })
}),
{
inspect: (ev) => {
events.push(ev);
}
}
);

const Component = () => {
const count = SomeContext.useSelector((state) => state.context.count);

return <div data-testid="value">{count}</div>;
};

const App = () => {
return (
<SomeContext.Provider options={{ input: 10 }}>
<Component />
</SomeContext.Provider>
);
};

render(<App />);

expect(events.length).toBeGreaterThan(0);
expect(events).toContainEqual(
expect.objectContaining({
snapshot: expect.objectContaining({
context: { count: 10 }
})
})
);
});
});

0 comments on commit 52900a0

Please sign in to comment.