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

Commit 477c227

Browse files
committed
🚧 (createCanal) Push Canal to Navigation service
1 parent 051f6e7 commit 477c227

8 files changed

Lines changed: 92 additions & 26 deletions

File tree

example/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, { Component } from 'react';
2+
import { StyleSheet } from 'react-native';
23
import { SignIn } from './canals/SignIn';
34

45
interface IProps {}
56
export default class App extends Component<IProps> {
67
render() {
7-
return <SignIn />;
8+
return <SignIn style={StyleSheet.absoluteFill} />;
89
}
910
}

src/Navigation.store.tsx

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
import { observable } from 'mobx';
1+
import { observable, computed, action } from 'mobx';
22
import { Subject } from 'rxjs';
3-
import { Canal } from 'Canal';
3+
import { Canal, IStop } from 'Canal';
44

5-
interface INavigationState {}
5+
interface INavigationEvent {
6+
canalId: Canal['id'];
7+
stop: IStop;
8+
}
9+
interface INavigationState {
10+
[key: string]: IStop[];
11+
}
612
interface ICanalsMap {
713
[key: string]: Canal;
814
}
@@ -23,12 +29,31 @@ export class Navigation {
2329
private canalsMapSubscription = this.canalsSubject.subscribe({
2430
next: (canal: Canal) => {
2531
this.canalsMap[canal.id] = canal;
32+
this.pushToHistory(canal, canal.stopsList[0]);
2633
},
2734
});
2835

2936
private canalsMap: ICanalsMap = {};
3037

3138
@observable
32-
// @ts-ignore
33-
private state: INavigationState = {};
39+
private history: INavigationEvent[] = [];
40+
41+
@action
42+
private pushToHistory = (canal: Canal, stop: IStop) => {
43+
this.history.push({
44+
canalId: canal.id,
45+
stop,
46+
});
47+
};
48+
49+
@computed get state(): INavigationState {
50+
const result = this.history.reduce(
51+
(previousState, navigationEvent) => ({
52+
...previousState,
53+
[navigationEvent.canalId]: [navigationEvent.stop],
54+
}),
55+
{}
56+
);
57+
return result;
58+
}
3459
}
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`createCanal renders the first page when mounted 1`] = `<View />`;
3+
exports[`createCanal renders the first page when mounted 1`] = `
4+
<View>
5+
<View
6+
style={
7+
Object {
8+
"bottom": 0,
9+
"left": 0,
10+
"position": "absolute",
11+
"right": 0,
12+
"top": 0,
13+
}
14+
}
15+
>
16+
<View />
17+
</View>
18+
</View>
19+
`;

src/__tests__/createCanal.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ describe('createCanal', () => {
1313
createCanal('aaa');
1414
} catch (error) {
1515
expect(error.message).toBe(
16-
'`createCanal` expects its first arguments to be a React component. Received type for argument 1: string'
16+
'`createCanal` expects its arguments to be React components. Received type for argument 1: string'
1717
);
1818
}
1919
expect.assertions(1);
@@ -25,13 +25,13 @@ describe('createCanal', () => {
2525
expect(testRenderer.toJSON()).toMatchSnapshot();
2626
});
2727

28-
it('throws an error if any first arg is not a Component', () => {
28+
it('throws an error if any arg is not a Component', () => {
2929
try {
3030
// @ts-ignore
3131
createCanal(View, 'aaa');
3232
} catch (error) {
3333
expect(error.message).toBe(
34-
'`createCanal` expects its first arguments to be a React component. Received type for argument 2: string'
34+
'`createCanal` expects its arguments to be React components. Received type for argument 2: string'
3535
);
3636
}
3737
expect.assertions(1);

src/canal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ComponentType } from 'react';
22

33
export interface IStop {
4-
component: ComponentType;
4+
Component: ComponentType;
55
name: string;
66
}
77

@@ -10,7 +10,7 @@ export class Canal {
1010
stopsList: IStop[] = [];
1111
constructor(PagesList: ComponentType[]) {
1212
this.stopsList = PagesList.map(Page => ({
13-
component: Page,
13+
Component: Page,
1414
name: Page.displayName || 'UntitledPage',
1515
}));
1616
}

src/createCanal.tsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,47 @@
1-
import React, { ComponentType, FunctionComponent, useEffect } from 'react';
1+
import React, { ComponentType, Component as ReactComponent } from 'react';
2+
import { ViewStyle, View, StyleSheet } from 'react-native';
3+
import { observer } from 'mobx-react/native';
24
import { Canal } from './Canal';
3-
import { useNavigation } from './NavigationContext';
5+
import { Navigation } from './Navigation.store';
46

5-
export const createCanal = (...PagesList: ComponentType[]): FunctionComponent => {
7+
interface ILocalTransitionerProps {
8+
style?: ViewStyle;
9+
}
10+
11+
export const createCanal = (
12+
...PagesList: ComponentType[]
13+
): ComponentType<ILocalTransitionerProps> => {
614
for (let index = 0; index < PagesList.length; index++) {
715
const Page = PagesList[index];
816
if (!(React.isValidElement(Page) || typeof Page === 'function')) {
917
throw new Error(
10-
`\`createCanal\` expects its first arguments to be a React component. Received type for argument ${index +
18+
`\`createCanal\` expects its arguments to be React components. Received type for argument ${index +
1119
1}: ${typeof Page}`
1220
);
1321
}
1422
}
15-
const LocalTransitioner = () => {
16-
const FirstPage = PagesList[0];
17-
const navigation = useNavigation();
18-
useEffect(() => {
19-
navigation.canalsSubject.next(new Canal(PagesList));
20-
}, [false]);
21-
return <FirstPage />;
22-
};
23+
24+
@observer
25+
class LocalTransitioner extends ReactComponent<ILocalTransitionerProps> {
26+
canal = new Canal(PagesList);
27+
28+
constructor(props: ILocalTransitionerProps) {
29+
super(props);
30+
const navigation = Navigation.getInstance();
31+
navigation.canalsSubject.next(this.canal);
32+
}
33+
34+
render() {
35+
return (
36+
<View style={this.props.style}>
37+
{Navigation.getInstance().state[this.canal.id].map(({ Component, name }) => (
38+
<View style={StyleSheet.absoluteFill} key={name}>
39+
<Component />
40+
</View>
41+
))}
42+
</View>
43+
);
44+
}
45+
}
2346
return LocalTransitioner;
2447
};

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"noEmit": true,
2626
"allowJs": true,
2727
"lib": ["es6"],
28-
"types": ["react-native"]
28+
"types": ["react-native", "mobx-react"]
2929
},
3030
"include": ["./src"],
3131
"exclude": [

tslint.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"trailing-comma": false,
99
"no-empty-interface": false,
1010
"member-access": false,
11-
"arrow-parens": false
11+
"arrow-parens": false,
12+
"semicolon": false
1213
},
1314
"rulesDirectory": []
1415
}

0 commit comments

Comments
 (0)