diff --git a/src/builders.spec.tsx b/src/builders.spec.tsx
index 44f16be..16bba29 100644
--- a/src/builders.spec.tsx
+++ b/src/builders.spec.tsx
@@ -107,16 +107,15 @@ describe("xstate-tree builders", () => {
const hist: XstateTreeHistory = createMemoryHistory();
const createRoute = buildCreateRoute(() => hist, "/");
- const fooRoute = createRoute.simpleRoute()({
- url: "/foo/",
- event: "GO_TO_FOO",
- });
- const barRoute = createRoute.simpleRoute()({
- url: "/bar/",
- event: "GO_TO_BAR",
- });
-
it("takes a mapping of routes to machines and returns a machine that invokes those machines when those routes events are broadcast", async () => {
+ const fooRoute = createRoute.simpleRoute()({
+ url: "/foo/",
+ event: "GO_TO_FOO",
+ });
+ const barRoute = createRoute.simpleRoute()({
+ url: "/bar/",
+ event: "GO_TO_BAR",
+ });
const FooMachine = viewToMachine(() =>
foo
);
const BarMachine = viewToMachine(() => bar
);
@@ -142,5 +141,40 @@ describe("xstate-tree builders", () => {
act(() => barRoute.navigate());
await waitFor(() => getByText("bar"));
});
+
+ it("handles routing events that contain . in them", async () => {
+ const fooRoute = createRoute.simpleRoute()({
+ url: "/foo/",
+ event: "routing.foo",
+ });
+ const barRoute = createRoute.simpleRoute()({
+ url: "/bar/",
+ event: "routing.bar",
+ });
+ const FooMachine = viewToMachine(() => foo
);
+ const BarMachine = viewToMachine(() => bar
);
+
+ const routingMachine = buildRoutingMachine([fooRoute, barRoute], {
+ "routing.foo": FooMachine,
+ "routing.bar": BarMachine,
+ });
+
+ const Root = buildRootComponent({
+ machine: routingMachine,
+ routing: {
+ history: hist,
+ basePath: "/",
+ routes: [fooRoute, barRoute],
+ },
+ });
+
+ const { getByText } = render();
+
+ act(() => fooRoute.navigate());
+ await waitFor(() => getByText("foo"));
+
+ act(() => barRoute.navigate());
+ await waitFor(() => getByText("bar"));
+ });
});
});
diff --git a/src/builders.tsx b/src/builders.tsx
index 5865e5c..fa34a1b 100644
--- a/src/builders.tsx
+++ b/src/builders.tsx
@@ -111,13 +111,22 @@ export function buildRoutingMachine(
_routes: TRoutes,
mappings: Record
): AnyXstateTreeMachine {
+ /**
+ * States in xstate can't contain dots, since the states are named after the routing events
+ * if the routing event contains a dot that will make a state with a dot in it
+ * this function sanitizes the event name to remove dots and is used for the state names and targets
+ */
+ function sanitizeEventName(event: string) {
+ return event.replace(/\.([a-zA-Z])/g, (_, letter) => letter.toUpperCase());
+ }
+
const contentSlot = singleSlot("Content");
const mappingsToStates = Object.entries(
mappings
).reduce((acc, [event, _machine]) => {
return {
...acc,
- [event]: {
+ [sanitizeEventName(event)]: {
invoke: {
src: event,
id: contentSlot.getId(),
@@ -130,7 +139,7 @@ export function buildRoutingMachine(
(acc, event) => ({
...acc,
[event]: {
- target: `.${event}`,
+ target: `.${sanitizeEventName(event)}`,
},
}),
{}