Browse code
Working prototype
Ed Langley authored on 17/06/2017 16:25:27
Showing 6 changed files
Showing 6 changed files
- .editorconfig
- .gitignore
- demos/doc_site/src/components/MenuSidebar.js
- demos/doc_site/src/model/index.js
- src/action-router.js
- src/change-url-event.test.js
... | ... |
@@ -1,14 +1,33 @@ |
1 | 1 |
import React from 'react'; |
2 | 2 |
import { SideNav, Link as SideNavLink } from '@cjdev/visual-stack/lib/components/SideNav'; |
3 |
+import { connect } from 'react-redux'; |
|
3 | 4 |
|
4 |
- |
|
5 |
-export default function({items}) { |
|
5 |
+function MenuSidebar({items, changePage}) { |
|
6 | 6 |
return ( |
7 | 7 |
<SideNav> |
8 |
- |
|
9 | 8 |
{items.map((item) => { |
10 |
- return <SideNavLink key={item.id}><a href={item.url}>{item.title}</a></SideNavLink> |
|
9 |
+ return ( |
|
10 |
+ <SideNavLink key={item.id}> |
|
11 |
+ <a onClick={ |
|
12 |
+ (ev) => { |
|
13 |
+ ev.preventDefault(); |
|
14 |
+ changePage(item.id); |
|
15 |
+ } |
|
16 |
+ }>{item.title}</a> |
|
17 |
+ </SideNavLink> |
|
18 |
+ ); |
|
11 | 19 |
})} |
12 | 20 |
</SideNav> |
13 | 21 |
); |
14 |
-}; |
|
15 | 22 |
\ No newline at end of file |
23 |
+}; |
|
24 |
+ |
|
25 |
+let mapDispatchToProps = (dispatch) => ({ |
|
26 |
+ changePage(id) { |
|
27 |
+ dispatch({type: 'CHANGE_ID', id}); |
|
28 |
+ } |
|
29 |
+}); |
|
30 |
+ |
|
31 |
+export default connect( |
|
32 |
+ () => ({}), |
|
33 |
+ mapDispatchToProps |
|
34 |
+)(MenuSidebar); |
... | ... |
@@ -73,7 +73,7 @@ const reduce = (state = defaultState, event) => { |
73 | 73 |
|
74 | 74 |
}; |
75 | 75 |
|
76 |
-const {middleware, enhancer} = installBrowserRouter([ |
|
76 |
+const {middleware, enhancer, init} = installBrowserRouter([ |
|
77 | 77 |
['/pages/:id', 'CHANGE_ID', {}], |
78 | 78 |
['/', 'CHANGE_ID', {id: 'home'}] |
79 | 79 |
]); |
... | ... |
@@ -94,6 +94,7 @@ const store = createStore(reduce, |
94 | 94 |
sagaMiddleware |
95 | 95 |
) |
96 | 96 |
)); |
97 |
+init(); |
|
97 | 98 |
|
98 | 99 |
const fetchArticle = function*({id}) { |
99 | 100 |
console.log('SAGA???'); |
... | ... |
@@ -133,4 +134,4 @@ export { |
133 | 134 |
actions, |
134 | 135 |
createDefaultState, |
135 | 136 |
sagas |
136 |
-}; |
|
137 | 137 |
\ No newline at end of file |
138 |
+}; |
... | ... |
@@ -283,6 +283,8 @@ function createActionDispatcher(routesConfig, window) { |
283 | 283 |
let {compiledActionMatchers, compiledRouteMatchers} = compileRoutes(routesConfig); |
284 | 284 |
|
285 | 285 |
let actionDispatcher = { |
286 |
+ currentLocation: null, |
|
287 |
+ |
|
286 | 288 |
store: null, |
287 | 289 |
activateDispatcher(store) { |
288 | 290 |
window.addEventListener('urlchanged', this); |
... | ... |
@@ -292,7 +294,6 @@ function createActionDispatcher(routesConfig, window) { |
292 | 294 |
return (reducer, finalInitialState, enhancer) => { |
293 | 295 |
let theStore = nextStoreCreator(reducer, finalInitialState, enhancer); |
294 | 296 |
this.activateDispatcher(theStore); |
295 |
- this.receiveLocation(window.location); |
|
296 | 297 |
return theStore; |
297 | 298 |
}; |
298 | 299 |
}, |
... | ... |
@@ -306,11 +307,14 @@ function createActionDispatcher(routesConfig, window) { |
306 | 307 |
this.receiveLocation(location); |
307 | 308 |
}, |
308 | 309 |
receiveLocation(location) { |
309 |
- const match = matchRoute(location, compiledRouteMatchers); |
|
310 |
- if(match) { |
|
311 |
- const action = constructAction(match); |
|
310 |
+ if (this.currentLocation !== location.pathname) { |
|
311 |
+ this.currentLocation = location.pathname; |
|
312 |
+ const match = matchRoute(location, compiledRouteMatchers); |
|
313 |
+ if(match) { |
|
314 |
+ const action = constructAction(match); |
|
312 | 315 |
|
313 |
- this.store.dispatch(action); |
|
316 |
+ this.store.dispatch(action); |
|
317 |
+ } |
|
314 | 318 |
} |
315 | 319 |
}, |
316 | 320 |
receiveAction(action) { |
... | ... |
@@ -345,5 +349,5 @@ export default function installBrowserRouter(routesConfig, window) { |
345 | 349 |
|
346 | 350 |
const middleware = buildMiddleware(actionDispatcher); |
347 | 351 |
|
348 |
- return {middleware, enhancer: actionDispatcher.enhanceStore}; |
|
352 |
+ return {middleware, enhancer: actionDispatcher.enhanceStore, init: actionDispatcher.receiveLocation.bind(actionDispatcher, window.location)}; |
|
349 | 353 |
} |
... | ... |
@@ -48,7 +48,6 @@ it("given event handler should generate a urlchange event only when url changes" |
48 | 48 |
if(map[evName]) { |
49 | 49 |
map[evName].handleEvent(ev); |
50 | 50 |
} |
51 |
- |
|
52 | 51 |
}); |
53 | 52 |
|
54 | 53 |
// when |
... | ... |
@@ -56,8 +55,6 @@ it("given event handler should generate a urlchange event only when url changes" |
56 | 55 |
window.dispatchEvent(new Event('popstate')); |
57 | 56 |
window.dispatchEvent(new Event('popstate')); |
58 | 57 |
|
59 |
- |
|
60 |
- |
|
61 | 58 |
// then |
62 | 59 |
expect(calls.length).toEqual(3); |
63 | 60 |
expect(calls[1].type).toEqual('urlchanged'); |
... | ... |
@@ -67,12 +64,12 @@ it("given event handler should generate a urlchange event only when url changes" |
67 | 64 |
window.location.pathname = '/new/path'; |
68 | 65 |
window.dispatchEvent(new Event('popstate')); |
69 | 66 |
|
70 |
- |
|
71 | 67 |
//then |
72 | 68 |
expect(calls.length).toEqual(5); |
73 | 69 |
expect(calls[4].type).toEqual('urlchanged'); |
74 | 70 |
expect(calls[4].detail).toEqual(window.location); |
75 | 71 |
|
72 |
+ console.log(map); |
|
76 | 73 |
}); |
77 | 74 |
|
78 | 75 |
it("should only add url events 1x when addChangeUrlEvent is called on window more than 1x", () => { |