-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathindex.js
116 lines (111 loc) · 2.84 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React from 'react'
import ReactDOM from 'react-dom'
const Weather = {
init: () => ({
query: '',
fetching: false,
error: undefined,
result: undefined,
}),
update: (state, action) => {
if (action.type === 'onChange') {
return {
...state,
query: action.payload
}
}
if (action.type === 'onSubmit') {
return {
...state,
fetching: true,
error: undefined,
result: undefined,
}
}
if (action.type === 'onError') {
return {
...state,
fetching: false,
error: action.payload,
}
}
if (action.type === 'onSuccess') {
return {
...state,
fetching: false,
result: action.payload,
}
}
},
view: ({dispatch, state}) => {
const error = state.error ? <div>{JSON.stringify(state.error)}</div> : false
const result = state.result ? <div>{state.result.name}: {state.result.weather[0].description}</div> : false
const fetching = state.fetching ? <div>loading...</div> : false
return (
<div>
<input
value={state.query}
onChange={e => dispatch({type: 'onChange', payload: e.target.value})}
/>
<button onClick={() => dispatch({type: 'onSubmit'})}>submit</button>
{fetching}
{error}
{result}
</div>
)
},
http: ({dispatch, state}) => {
if (state.fetching) {
return {
[state.query]: {
method: 'get',
url: `http://api.openweathermap.org/data/2.5/weather?APPID=d1038f86626c191d14fde59a7f548d6c&q=${state.query}`,
onSuccess: json => dispatch({type: 'onSuccess', payload: json}),
onError: error => dispatch({type: 'onError', payload: error}),
}
}
}
return {}
}
}
const ReactDriver = (app, dispatch) => {
const root = document.getElementById('root')
return state => {
ReactDOM.render(app.view({dispatch, state}), root)
}
}
const HttpDriver = (app, dispatch) => {
let pending = {}
return state => {
const requests = app.http({dispatch, state})
Object.keys(requests).forEach(key => {
if (!pending[key]) {
const req = requests[key]
fetch(req.url, req)
.then(response => response.json())
.then(json => {
if (pending[key]) {
pending[key].onSuccess(json)
}
})
.catch(error => {
if (pending[key]) {
pending[key].onError(error)
}
})
}
})
pending = requests
}
}
const configure = drivers => app => {
let state = app.init()
const listeners = drivers.map(d => d(app, dispatch))
function dispatch(action) {
state = app.update(state, action)
listeners.forEach(l => l(state))
}
listeners.forEach(l => l(state))
}
const start = configure([ReactDriver, HttpDriver])
start(Weather)