|
| 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 |
0 commit comments