Skip to content
This repository was archived by the owner on Nov 3, 2025. It is now read-only.

Commit 051f6e7

Browse files
committed
🚧 (canal) Subscribe Navigation store to canal creation
1 parent b7152d5 commit 051f6e7

9 files changed

Lines changed: 63 additions & 32 deletions

File tree

__mocks__/react.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* useEffect does not trigger on render.
3+
* See https://github.com/facebook/react/issues/14050#issuecomment-438173736.
4+
* @TODO 2019-05-15 Check if this can be removed
5+
*/
6+
7+
const React = require.requireActual('react');
8+
module.exports = { ...React, useEffect: React.useLayoutEffect };

src/Navigation.store.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { observable } from 'mobx';
2+
import { Subject } from 'rxjs';
23
import { Canal } from 'Canal';
34

45
interface INavigationState {}
@@ -16,8 +17,18 @@ export class Navigation {
1617
}
1718
private static instance: Navigation;
1819

20+
canalsSubject = new Subject<Canal>();
21+
22+
// @ts-ignore
23+
private canalsMapSubscription = this.canalsSubject.subscribe({
24+
next: (canal: Canal) => {
25+
this.canalsMap[canal.id] = canal;
26+
},
27+
});
28+
1929
private canalsMap: ICanalsMap = {};
2030

2131
@observable
32+
// @ts-ignore
2233
private state: INavigationState = {};
2334
}

src/__tests__/Canal.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Canal } from '../Canal';
22

33
describe('Canal', () => {
44
it('initializes with a unique id', () => {
5-
const canal = new Canal();
5+
const canal = new Canal([]);
66
expect(canal.id).toEqual(0);
77
});
88
});

src/__tests__/Navigation.store.test.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
import { Navigation } from '../Navigation.store';
22

33
describe('Navigation store', () => {
4-
it('exposes the store instance', () => {
5-
const expectedNavigation = new Navigation();
6-
const navigation = Navigation.getInstance();
7-
expect(navigation).toEqual(expectedNavigation);
8-
});
9-
104
it('exposes the same store instance if it accessed twice', () => {
115
const navigation = Navigation.getInstance();
126
const otherNavigation = Navigation.getInstance();

src/__tests__/NavigationContext.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Navigation } from '../Navigation.store';
88
describe('NavigationContext', () => {
99
describe('NavigationConsumer', () => {
1010
it('connects to context and exposes the navigation prop', () => {
11-
const expectedNavigation = new Navigation();
11+
const expectedNavigation = Navigation.getInstance();
1212
TestRenderer.create(
1313
<NavigationConsumer>
1414
{navigation => {
@@ -22,7 +22,7 @@ describe('NavigationContext', () => {
2222
});
2323
describe('withNavigation', () => {
2424
it('connects to context and exposes the navigation prop', () => {
25-
const expectedNavigation = new Navigation();
25+
const expectedNavigation = Navigation.getInstance();
2626
// @ts-ignore
2727
const ViewWithNavigation = withNavigation(View);
2828
const testRenderer = TestRenderer.create(<ViewWithNavigation />);
@@ -33,7 +33,7 @@ describe('NavigationContext', () => {
3333
});
3434
describe('useNavigation', () => {
3535
it('connects to context and exposes the navigation prop', () => {
36-
const expectedNavigation = new Navigation();
36+
const expectedNavigation = Navigation.getInstance();
3737
const ViewWithNavigation = () => {
3838
const navigation = useNavigation();
3939
// @ts-ignore
Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`createCanal renders the first page when mounted 1`] = `
4-
<View
5-
navigation={
6-
Navigation {
7-
"canalsMap": Object {},
8-
}
9-
}
10-
/>
11-
`;
3+
exports[`createCanal renders the first page when mounted 1`] = `<View />`;

src/__tests__/createCanal.test.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { View } from 'react-native';
33
import TestRenderer from 'react-test-renderer';
44

55
import { createCanal } from '../createCanal';
6+
import { Navigation } from '../Navigation.store';
7+
import { Canal } from '../Canal';
68

79
describe('createCanal', () => {
810
it('throws an error if first arg is not a Component', () => {
@@ -18,8 +20,8 @@ describe('createCanal', () => {
1820
});
1921

2022
it('renders the first page when mounted', () => {
21-
const Canal = createCanal(View);
22-
const testRenderer = TestRenderer.create(<Canal />);
23+
const Transitioner = createCanal(View);
24+
const testRenderer = TestRenderer.create(<Transitioner />);
2325
expect(testRenderer.toJSON()).toMatchSnapshot();
2426
});
2527

@@ -34,4 +36,18 @@ describe('createCanal', () => {
3436
}
3537
expect.assertions(1);
3638
});
39+
40+
it('emits the new canal to the navigation store', () => {
41+
const PageOne = () => <View />;
42+
const PageTwo = () => <View />;
43+
const Transitioner = createCanal(PageOne, PageTwo);
44+
const expectedCanal = new Canal([PageOne, PageTwo]);
45+
Navigation.getInstance().canalsSubject.subscribe({
46+
next: canal => {
47+
expect(canal).toEqual(expectedCanal);
48+
},
49+
});
50+
TestRenderer.create(<Transitioner />);
51+
expect.assertions(1);
52+
});
3753
});

src/canal.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
import { ComponentType } from 'react';
2+
13
export interface IStop {
4+
component: ComponentType;
25
name: string;
36
}
47

58
export class Canal {
69
id: number = Date.now();
710
stopsList: IStop[] = [];
11+
constructor(PagesList: ComponentType[]) {
12+
this.stopsList = PagesList.map(Page => ({
13+
component: Page,
14+
name: Page.displayName || 'UntitledPage',
15+
}));
16+
}
817
}

src/createCanal.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1-
import React, { ComponentType, FunctionComponent } from 'react';
2-
import { Navigation } from 'Navigation.store';
1+
import React, { ComponentType, FunctionComponent, useEffect } from 'react';
2+
import { Canal } from './Canal';
33
import { useNavigation } from './NavigationContext';
44

5-
export const createCanal = (
6-
...Pages: Array<ComponentType<{ navigation: Navigation }>>
7-
): FunctionComponent => {
8-
for (let index = 0; index < Pages.length; index++) {
9-
const Page = Pages[index];
5+
export const createCanal = (...PagesList: ComponentType[]): FunctionComponent => {
6+
for (let index = 0; index < PagesList.length; index++) {
7+
const Page = PagesList[index];
108
if (!(React.isValidElement(Page) || typeof Page === 'function')) {
119
throw new Error(
1210
`\`createCanal\` expects its first arguments to be a React component. Received type for argument ${index +
1311
1}: ${typeof Page}`
1412
);
1513
}
1614
}
17-
const FirstPage = Pages[0];
18-
const Canal = () => {
15+
const LocalTransitioner = () => {
16+
const FirstPage = PagesList[0];
1917
const navigation = useNavigation();
20-
return <FirstPage navigation={navigation} />;
18+
useEffect(() => {
19+
navigation.canalsSubject.next(new Canal(PagesList));
20+
}, [false]);
21+
return <FirstPage />;
2122
};
22-
return Canal;
23+
return LocalTransitioner;
2324
};

0 commit comments

Comments
 (0)