@@ -12,19 +12,19 @@ You'll need to setup the project before you get to actual coding.
1212You need a React project in order to start using tea-cup.
1313In order to keep things simple, we'll use the infamous ` create-react-app ` :
1414
15- npx create- react-app my-app --typescript
15+ yarn create react-app my-app --template typescript
1616 cd my-app
1717
1818### Add tea-cup to your dependencies
1919
20- npm install react-tea-cup --save
20+ yarn add -D react-tea-cup tea-cup-core
2121
2222### Run the dev server
2323
2424We'll start the dev server, and let it recompile everything
2525when we save files :
2626
27- npm start
27+ yarn start
2828
2929This should also open your default browser to http://localhost:3000
3030and show you the default generated app.
@@ -37,7 +37,8 @@ favourite editor, and replace its contents with this :
3737``` typescript jsx
3838import React from ' react' ;
3939// bare minimum to use tea-cup
40- import { Dispatcher , Cmd , Program , Sub } from ' react-tea-cup' ;
40+ import { Program } from ' react-tea-cup' ;
41+ import { Cmd , Dispatcher , Sub } from ' tea-cup-core' ;
4142
4243// a Model can be anything. Here, it's simply a number...
4344type Model = number ;
@@ -115,185 +116,186 @@ and Cmds.
115116Replace the contents of ` App.tsx ` with the following, code :
116117
117118``` typescript jsx
118- import {Http , Cmd , Task , Result , Dispatcher , Decode , Decoder , Maybe , nothing , Sub , Program , just } from " react-tea-cup" ;
119+ import {Http , Cmd , Task , Result , Dispatcher , Decode , Decoder , Maybe , nothing , Sub , just } from " tea-cup-core" ;
120+ import {Program } from " react-tea-cup" ;
119121import * as React from ' react'
120122
121123
122124interface Model {
123- // name of the repo
124- readonly repo: string
125- // use Maybe of Result to model state :
126- // * nothing : loading commits
127- // * just(error) : last fetch has failed, we have the error
128- // * just(commit[]) : last fetch succeeded, we havbe the commits
129- readonly commits: Maybe <Result <Error ,ReadonlyArray <Commit >>>
125+ // name of the repo
126+ readonly repo: string
127+ // use Maybe of Result to model state :
128+ // * nothing : loading commits
129+ // * just(error) : last fetch has failed, we have the error
130+ // * just(commit[]) : last fetch succeeded, we havbe the commits
131+ readonly commits: Maybe <Result <Error ,ReadonlyArray <Commit >>>
130132}
131-
133+
132134interface Commit {
133- readonly sha: string
134- readonly author: string
135+ readonly sha: string
136+ readonly author: string
135137}
136-
137138
138- type Msg
139- // repo name changed
140- = { type: " repo-changed" , value: string }
141- // trigger a fetch of commits
142- | { type: " fetch" }
143- // got fetch response, or an error
144- | { type: " got-commits" , commits: Result <Error ,ReadonlyArray <Commit >> }
139+
140+ type Msg
141+ // repo name changed
142+ = { type: " repo-changed" , value: string }
143+ // trigger a fetch of commits
144+ | { type: " fetch" }
145+ // got fetch response, or an error
146+ | { type: " got-commits" , commits: Result <Error ,ReadonlyArray <Commit >> }
145147
146148
147149function init(repo : string ): [Model , Cmd <Msg >] {
148- return [
149- {
150- repo: repo , // store initial repo name
151- commits: nothing // initial state is "loading"
152- },
153- fetchCommits (repo ) // initial fetch
154- ]
150+ return [
151+ {
152+ repo: repo , // store initial repo name
153+ commits: nothing // initial state is "loading"
154+ },
155+ fetchCommits (repo ) // initial fetch
156+ ]
155157}
156158
157159function view(dispatch : Dispatcher <Msg >, model : Model ) {
158- return (
159- <>
160- <h1 >
161- Fetch data using Http module
162- < / h1 >
163- < input
164- type = " text"
165- value = {model.repo }
166- onChange = {e => {
167- // update repo name on input change
168- const value = (e .target as HTMLInputElement ).value ;
169- dispatch ({
170- type: " repo-changed" ,
171- value: value
172- })
173- }}/ >
174- < button
175- disabled = {
176- // disable the button if we are fetching
177- model.commits.type === " Nothing"
178- }
179- onClick = {() =>
180- // fetch commits on click
181- dispatch({ type : " fetch" })
182- }
183- >
184- Fetch commits
185- < / button >
186- < hr / >
187- {
188- model .commits
189- // commits are present : map the result
190- .map (commitsResult = >
191- // use Result.match to map the result
192- // depending if it's ok, or an error
193- commitsResult .match (
194- // all good, we have commits, build the vdom
195- commits = >
196- <ul >
197- { commits .map (commit = >
198- <li key = {commit.sha }>
199- {commit .sha } - {commit .author }
200- </li >
201- )}
202- </ul >,
203- // in case there's an error, show it
204- error = >
205- <p >Fetch error : {error .message }</p >
206- )
207- )
208- // commits == nothing, we are currently fetching
209- .withDefault (
210- <p >Fetching ... < / p >
211- )
212- }
213- < / >
214- )
160+ return (
161+ <>
162+ <h1 >
163+ Fetch data using Http module
164+ < / h1 >
165+ < input
166+ type = " text"
167+ value = {model.repo }
168+ onChange = {e => {
169+ // update repo name on input change
170+ const value = (e .target as HTMLInputElement ).value ;
171+ dispatch ({
172+ type: " repo-changed" ,
173+ value: value
174+ })
175+ }}/ >
176+ < button
177+ disabled = {
178+ // disable the button if we are fetching
179+ model.commits.type === " Nothing"
180+ }
181+ onClick = {() =>
182+ // fetch commits on click
183+ dispatch({ type : " fetch" })
184+ }
185+ >
186+ Fetch commits
187+ < / button >
188+ < hr / >
189+ {
190+ model .commits
191+ // commits are present : map the result
192+ .map (commitsResult = >
193+ // use Result.match to map the result
194+ // depending if it's ok, or an error
195+ commitsResult .match (
196+ // all good, we have commits, build the vdom
197+ commits = >
198+ <ul >
199+ { commits .map (commit = >
200+ <li key = {commit.sha }>
201+ {commit .sha } - {commit .author }
202+ </li >
203+ )}
204+ </ul >,
205+ // in case there's an error, show it
206+ error = >
207+ <p >Fetch error : {error .message }</p >
208+ )
209+ )
210+ // commits == nothing, we are currently fetching
211+ .withDefault (
212+ <p >Fetching ... < / p >
213+ )
214+ }
215+ < / >
216+ )
215217}
216218
217219function update(msg : Msg , model : Model ): [Model , Cmd <Msg >] {
218- switch (msg .type ) {
219- case " repo-changed" :
220- // just change the repo in Model
221- return [
222- { ... model , repo: msg .value },
223- Cmd .none ()
224- ]
225- case " fetch" :
226- // indicate that we are fetching (set commits to nothing)
227- // and trigger thje fetch
228- return [
229- { ... model , commits: nothing },
230- fetchCommits (model .repo )
231- ]
232- case " got-commits" :
233- // got the fetch response, assign it to
234- // the Model
235- return [
236- { ... model , commits: just (msg .commits ) },
237- Cmd .none ()
238- ]
239- }
220+ switch (msg .type ) {
221+ case " repo-changed" :
222+ // just change the repo in Model
223+ return [
224+ { ... model , repo: msg .value },
225+ Cmd .none ()
226+ ]
227+ case " fetch" :
228+ // indicate that we are fetching (set commits to nothing)
229+ // and trigger thje fetch
230+ return [
231+ { ... model , commits: nothing },
232+ fetchCommits (model .repo )
233+ ]
234+ case " got-commits" :
235+ // got the fetch response, assign it to
236+ // the Model
237+ return [
238+ { ... model , commits: just (msg .commits ) },
239+ Cmd .none ()
240+ ]
241+ }
240242}
241243
242244// no subs in this example
243245function subscriptions(model : Model ): Sub <Msg > {
244- return Sub .none ()
246+ return Sub .none ()
245247}
246248
247249// create and return a Cmd that fetches commits
248250// for the passed repo
249251function fetchCommits(repo : string ): Cmd <Msg > {
250- // create a Task that fetches the commits or fails with an Error
251- const fetchTask: Task <Error ,ReadonlyArray <Commit >> =
252- Http .jsonBody (
253- // create a fetch Task
254- Http .fetch (` https://api.github.com/repos/${repo }/commits ` ),
255- // decode the response with this decoder
256- Decode .array (commitDecoder )
257- );
258-
259- // Msg creator function
260- function gotCommits(r : Result <Error ,ReadonlyArray <Commit >>): Msg {
261- return {
262- type: " got-commits" ,
263- commits: r
252+ // create a Task that fetches the commits or fails with an Error
253+ const fetchTask: Task <Error ,ReadonlyArray <Commit >> =
254+ Http .jsonBody (
255+ // create a fetch Task
256+ Http .fetch (` https://api.github.com/repos/${repo }/commits ` ),
257+ // decode the response with this decoder
258+ Decode .array (commitDecoder )
259+ );
260+
261+ // Msg creator function
262+ function gotCommits(r : Result <Error ,ReadonlyArray <Commit >>): Msg {
263+ return {
264+ type: " got-commits" ,
265+ commits: r
266+ }
264267 }
265- }
266-
267- // "perform" the Task, and indicate which message
268- // needs to be used for handling the response
269- return Task .attempt (fetchTask ,gotCommits );
268+
269+ // "perform" the Task, and indicate which message
270+ // needs to be used for handling the response
271+ return Task .attempt (fetchTask ,gotCommits );
270272}
271273
272274
273275// create a Msg to handle the response of the fetch
274276
275277// A decoder for Commit objects
276278const commitDecoder: Decoder <Commit > =
277- Decode .map2 (
278- (sha : string , author : string ) => {
279- return {
280- sha: sha ,
281- author: author
282- }
283- },
284- Decode .field (" sha" , Decode .str ),
285- Decode .at ([" commit" , " author" ," name" ], Decode .str )
286- );
279+ Decode .map2 (
280+ (sha : string , author : string ) => {
281+ return {
282+ sha: sha ,
283+ author: author
284+ }
285+ },
286+ Decode .field (" sha" , Decode .str ),
287+ Decode .at ([" commit" , " author" ," name" ], Decode .str )
288+ );
287289
288290
289291// wire the program
290292const App = () => (
291- < Program
292- init = {() => init(" Microsoft/TypeScript" )}
293- view = {view }
294- update = {update }
295- subscriptions = {subscriptions }
296- / >
293+ < Program
294+ init = {() => init(" Microsoft/TypeScript" )}
295+ view = {view }
296+ update = {update }
297+ subscriptions = {subscriptions }
298+ / >
297299);
298300
299301export default App ;
0 commit comments