Skip to content

Commit 467e80d

Browse files
committed
time travel example
1 parent ee6197f commit 467e80d

File tree

8 files changed

+40807
-11
lines changed

8 files changed

+40807
-11
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Github Repo Type N Search Example
2+
3+
https://oyanglul.us/react-most/examples/type-n-search/public/
4+
5+
## install
6+
```sh
7+
npm install
8+
npm run build
9+
npm start
10+
```
11+
12+
## Code Walk Through
13+
14+
it's really simple example(only 40 LOC) that reactively search github repo according to your query
15+
16+
0. create normal React Component
17+
18+
```js
19+
const TypeNsearch = (props)=>{
20+
let {search} = props.actions
21+
return <div>
22+
<input onChange={e=>search(e.target.value)}></input>
23+
<ul>
24+
{props.results&&props.results.map(item=>{
25+
return <li key={item.id}><a href={item.html_url}>{item.full_name} ({item.stargazers_count})</a></li>
26+
})}
27+
</ul>
28+
</div>
29+
}
30+
```
31+
32+
1. HOC(Higher Order Component)
33+
using `connect` to create a HOC over TypeNsearch
34+
35+
```js
36+
const MostTypeNSearch = connect(DATAFLOW)(TypeNsearch)
37+
```
38+
2. Compose Dataflow
39+
you see the place holder `DATAFLOW`, now we gonna fill in the real data flow how we enable the reactive action of our Component
40+
1. filter out stream only with `intent.type` of 'search'
41+
42+
```js
43+
function(intent$){
44+
let updateSink$ = intent$.filter(i=>i.type=='search')
45+
.debounce(500)
46+
...
47+
```
48+
using `debounce` will transform the stream to stream which only bouncing at certain time point
49+
```
50+
---冷笑--冷笑话-->
51+
52+
--------冷笑话-->
53+
```
54+
2. compose a VALID query URL
55+
56+
```js
57+
...
58+
.map(intent=>intent.value)
59+
.filter(query=>query.length > 0)
60+
.map(query=>GITHUB_SEARCH_API + query)
61+
...
62+
```
63+
3. flatMap the Response to our stream
64+
```js
65+
.flatMap(url=>most.fromPromise(
66+
rest(url).then(resp=>({
67+
type: 'dataUpdate',
68+
value: resp.entity
69+
}))))
70+
```
71+
72+
`flatMap` is simply just `map` and then `flat`
73+
74+
> just pretent one `-` as one sec
75+
76+
```
77+
intentStream --urlA---urlB--->
78+
rest(urlA) -------respA---->
79+
rest(urlB) ---------respB-->
80+
flatMap(rest)-------respA--respB--->
81+
```
82+
4. model
83+
now our intent stream become a data stream, let's make it a modle stream.
84+
``` js
85+
.filter(i=>i.type=='dataUpdate')
86+
.map(data=>JSON.parse(data.value).items)
87+
.map(items=>items.slice(0,10))
88+
```
89+
parse it to JS Object and only get the first ten results
90+
5. create state transforming stream
91+
```
92+
.map(items=>state=>({results: items}))
93+
```
94+
95+
```
96+
modleStream ---mA---mB--->
97+
stateStream ---state=>({results:mA})---state=>({results:mB})--->
98+
```
99+
100+
3. return `actions` and `sinks`
101+
```js
102+
return {
103+
search: value=>({type:'search',value}),
104+
updateSink$,
105+
}
106+
```
107+
return `search` then you can use `props.actions.search` in your Component
108+
109+
return `updateSink$` then it can be appled to HOC's state, HOC will pass the state to your Component as props
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"name": "react-most-type-n-search",
3+
"version": "0.0.1",
4+
"description": "",
5+
"browserify": {
6+
"transform": [
7+
[
8+
"babelify",
9+
{
10+
"extensions": [
11+
".es6",
12+
".jsx",
13+
".js"
14+
]
15+
}
16+
]
17+
]
18+
},
19+
"scripts": {
20+
"build": "NODE_ENV=production browserify src/app.jsx --extension=.jsx --extension=.es6| java -jar ../todomvc/bin/compiler.jar > public/app.js",
21+
"start": "ecstatic -p 8000 public",
22+
"watch": "watchify -d src/app.jsx --extension=.jsx --extension=.es6 -o public/app.js -dv",
23+
"test": "jest"
24+
},
25+
"jest": {
26+
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
27+
"testFileExtensions": [
28+
"es6",
29+
"js",
30+
"jsx"
31+
],
32+
"moduleFileExtensions": [
33+
"js",
34+
"json",
35+
"es6",
36+
"jsx"
37+
]
38+
},
39+
"dependencies": {
40+
"classnames": "^2.2.0",
41+
"lodash": "^4.0.0",
42+
"react": "^0.14.2",
43+
"react-dom": "^0.14.2",
44+
"rest": "^1.3.1"
45+
},
46+
"devDependencies": {
47+
"babel": "^6.1.18",
48+
"babel-jest": "^6.0.0",
49+
"babel-plugin-lodash": "^2.0.1",
50+
"babel-plugin-transform-react-jsx": "^6.1.18",
51+
"babel-preset-es2015": "^6.1.18",
52+
"babelify": "^7.2.0",
53+
"browserify": "^12.0.1",
54+
"ecstatic": "^1.3.1",
55+
"jest-cli": "^0.7.0",
56+
"uglify-js": "^2.6.1",
57+
"watchify": "^3.6.1"
58+
},
59+
"author": "Jichao Ouyang",
60+
"license": "ISC",
61+
"babel": {
62+
"presets": [
63+
"es2015"
64+
],
65+
"plugins": [
66+
"transform-react-jsx",
67+
"lodash"
68+
]
69+
}
70+
}

0 commit comments

Comments
 (0)