From bc715d99001704618f1bacb76b115c072676f4d1 Mon Sep 17 00:00:00 2001 From: eric thul Date: Mon, 26 Nov 2018 08:38:32 -0500 Subject: [PATCH 1/5] Update example for hooks --- bower.json | 8 ++- package.json | 4 +- src/Example/TodoForm.purs | 70 ++++++++++++------------ src/Example/TodoItem.purs | 33 ++++++------ src/Example/TodoList.purs | 93 +++++++++++++++----------------- src/Main.purs | 70 ++++++++++++------------ yarn.lock | 108 +++++++++++--------------------------- 7 files changed, 169 insertions(+), 217 deletions(-) diff --git a/bower.json b/bower.json index a63a526..de10be1 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,11 @@ "dependencies": { "purescript-react-dom": "^6.0.0", "purescript-console": "^4.0.0", - "purescript-react": "^6.0.0", - "purescript-web-html": "^1.0.0" + "purescript-react": "hooks", + "purescript-web-html": "^1.0.0", + "purescript-free": "^5.1.0" + }, + "resolutions": { + "purescript-react": "hooks" } } diff --git a/package.json b/package.json index 2e9e9f6..5436cfd 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "webpack-dev-server": "DEBUG=* webpack-dev-server --mode development --progress --inline --hot" }, "dependencies": { - "react": "^16.0.0", - "react-dom": "^16.0.0" + "react": "^16.7.0-alpha.2", + "react-dom": "^16.7.0-alpha.2" }, "devDependencies": { "pscid": "^2.0.2", diff --git a/src/Example/TodoForm.purs b/src/Example/TodoForm.purs index 5ac6bd1..f43ae08 100644 --- a/src/Example/TodoForm.purs +++ b/src/Example/TodoForm.purs @@ -5,8 +5,10 @@ import Prelude import Effect (Effect) import Data.Maybe (Maybe, maybe, isNothing) +import Data.Tuple (Tuple(..)) import React as React +import React.Hooks as Hooks import React.SyntheticEvent as Event import React.DOM as DOM import React.DOM.Props as Props @@ -21,45 +23,41 @@ type TodoFormProps , onAdd :: Todo -> Effect Unit } -todoFormClass :: React.ReactClass TodoFormProps -todoFormClass = React.component "TodoForm" component +todoForm :: TodoFormProps -> Effect React.ReactElement +todoForm + { todo + , onEdit + , onAdd + } = render <$> Hooks.useState "" where - component this = - pure { state: {} - , render: render <$> React.getProps this - } + render (Tuple value setState) = + DOM.form + [ Props.onSubmit onSubmit ] + [ DOM.input + [ Props._type "text" + , Props.value value + --, Props.onChange onChange + , Props.onChange \event -> Hooks.setState setState (unsafeCoerce event).target.value + ] + , DOM.button + [ Props._type "submit" + , Props.disabled isDisabled + ] + [ DOM.text "Add" ] + ] where - render - { todo - , onEdit - , onAdd - } = - DOM.form - [ Props.onSubmit onSubmit ] - [ DOM.input - [ Props._type "text" - , Props.value value - , Props.onChange onChange - ] - , DOM.button - [ Props._type "submit" - , Props.disabled isDisabled - ] - [ DOM.text "Add" ] - ] - where - value = maybe "" (\(Todo { text }) -> text) todo + value'' = maybe "" (\(Todo { text }) -> text) todo - isDisabled = isNothing todo + isDisabled = isNothing todo - onSubmit event = do - Event.preventDefault event + onSubmit event = do + Event.preventDefault event - maybe (pure unit) onAdd todo + maybe (pure unit) onAdd todo - onChange event = onEdit $ - maybe (Todo { text, status: TodoPending }) - (\(Todo todo_) -> Todo todo_ { text = text }) - todo - where - text = (unsafeCoerce event).target.value + onChange'' event = onEdit $ + maybe (Todo { text, status: TodoPending }) + (\(Todo todo_) -> Todo todo_ { text = text }) + todo + where + text = (unsafeCoerce event).target.value diff --git a/src/Example/TodoItem.purs b/src/Example/TodoItem.purs index 6d22aa6..16d5949 100644 --- a/src/Example/TodoItem.purs +++ b/src/Example/TodoItem.purs @@ -2,6 +2,8 @@ module Example.TodoItem where import Prelude +import Effect (Effect) + import React as React import React.DOM as DOM import React.DOM.Props as Props @@ -10,20 +12,19 @@ import Example.Types (Todo(..), TodoStatus(..)) type TodoItemProps = { todo :: Todo } -todoItemClass :: React.ReactClass TodoItemProps -todoItemClass = React.component "TodoItem" component +todoItem :: TodoItemProps -> Effect React.ReactElement +todoItem + { todo: Todo + { text + , status + } + } = pure $ + DOM.div + [ Props.style { textDecoration } ] + [ React.toElement text ] where - component this = - pure { state: {} - , render: render <$> React.getProps this - } - where - render { todo: Todo { text, status } } = - DOM.div - [ Props.style { textDecoration } ] - [ React.toElement text ] - where - textDecoration = - case status of - TodoDone -> "line-through" - _ -> "none" + textDecoration = + case status of + TodoDone -> "line-through" + _ -> "none" + diff --git a/src/Example/TodoList.purs b/src/Example/TodoList.purs index 60fb277..ff4ad20 100644 --- a/src/Example/TodoList.purs +++ b/src/Example/TodoList.purs @@ -11,8 +11,8 @@ import React as React import React.DOM as DOM import React.DOM.Props as Props -import Example.TodoForm (todoFormClass) -import Example.TodoItem (todoItemClass) +import Example.TodoForm (todoForm) +import Example.TodoItem (todoItem) import Example.Types (Todo(..), TodoStatus(..)) type TodoListProps @@ -24,55 +24,48 @@ type TodoListProps , onClear :: Todo -> Effect Unit } -todoListClass :: React.ReactClass TodoListProps -todoListClass = React.component "TodoList" component - where - component this = - pure { state: {} - , render: render <$> React.getProps this - } - where - render - { todos - , todo - , onAdd - , onEdit - , onDone - , onClear - } = - DOM.div +todoList :: TodoListProps -> Effect React.ReactElement +todoList + { todos + , todo + , onAdd + , onEdit + , onDone + , onClear + } = pure $ + DOM.div + [ ] + [ React.createElementHooks todoForm + { todo + , onEdit + , onAdd + } + , DOM.ol [ ] - [ React.createLeafElement todoFormClass - { todo - , onEdit - , onAdd - } - , DOM.ol - [ ] - (renderItem <$> todos') - ] - where - todos' = filter (\(Todo { status }) -> TodoCleared /= status) todos + (renderItem <$> todos') + ] + where + todos' = filter (\(Todo { status }) -> TodoCleared /= status) todos - renderItem todo' @ Todo { status } = - DOM.li - [ ] - [ React.createLeafElement todoItemClass { todo: todo' } - , DOM.button - [ Props._type "button" - , Props.onClick onClick - ] - [ DOM.text text ] + renderItem todo' @ Todo { status } = + DOM.li + [ ] + [ React.createElementHooks todoItem { todo: todo' } + , DOM.button + [ Props._type "button" + , Props.onClick onClick ] - where - text = - case status of - TodoPending -> "Done" - TodoDone -> "Clear" - _ -> "" + [ DOM.text text ] + ] + where + text = + case status of + TodoPending -> "Done" + TodoDone -> "Clear" + _ -> "" - onClick event = - case status of - TodoPending -> onDone todo' - TodoDone -> onClear todo' - _ -> pure unit + onClick event = + case status of + TodoPending -> onDone todo' + TodoDone -> onClear todo' + _ -> pure unit diff --git a/src/Main.purs b/src/Main.purs index 4ff1e4e..809573e 100644 --- a/src/Main.purs +++ b/src/Main.purs @@ -6,6 +6,7 @@ import Effect (Effect) import Data.Array (snoc, modifyAt, elemIndex) import Data.Maybe (Maybe(..), fromJust, fromMaybe) +import Data.Tuple (Tuple(..)) import Web.HTML.HTMLDocument (toNonElementParentNode) as DOM import Web.DOM.NonElementParentNode (getElementById) as DOM @@ -15,9 +16,10 @@ import Web.HTML.Window (document) as DOM import Partial.Unsafe (unsafePartial) import React as React +import React.Hooks as Hooks import ReactDOM as ReactDOM -import Example.TodoList (todoListClass) +import Example.TodoList (todoList) import Example.Types (Todo(..), TodoStatus(..)) main :: Effect Unit @@ -34,46 +36,44 @@ main = void $ do let element' = unsafePartial (fromJust element) - ReactDOM.render (React.createLeafElement mainClass { }) element' + ReactDOM.render (React.createElementHooks wrapper { }) element' -mainClass :: React.ReactClass { } -mainClass = React.component "Main" component +wrapper :: { } -> Effect React.ReactElement +wrapper _ = render <$> Hooks.useState initialState where - component this = - pure { state: - { todo: Nothing - , todos: [] - } - , render: render <$> React.getState this - } - where - render + initialState = + { todo: Nothing + , todos: [] + } + + render + (Tuple { todo , todos - } = - React.createLeafElement todoListClass - { todos - , todo - - , onAdd: \todo' -> React.modifyState this \a -> - a { todo = Nothing - , todos = snoc a.todos todo' - } + } setState) = + React.createElementHooks todoList + { todos + , todo + + , onAdd: \todo' -> Hooks.modifyState setState \a -> + a { todo = Nothing + , todos = snoc a.todos todo' + } - , onEdit: \todo' -> React.modifyState this - _ { todo = Just todo' - } + , onEdit: \todo' -> Hooks.modifyState setState + _ { todo = Just todo' + } - , onDone: \todo' -> React.modifyState this \a -> - a { todos = setStatus a.todos todo' TodoDone - } + , onDone: \todo' -> Hooks.modifyState setState \a -> + a { todos = setStatus a.todos todo' TodoDone + } - , onClear : \todo' -> React.modifyState this \a -> - a { todos = setStatus a.todos todo' TodoCleared - } - } + , onClear : \todo' -> Hooks.modifyState setState \a -> + a { todos = setStatus a.todos todo' TodoCleared + } + } - setStatus todos todo status = fromMaybe todos $ do - i <- elemIndex todo todos + setStatus todos todo status = fromMaybe todos $ do + i <- elemIndex todo todos - modifyAt i (\(Todo a) -> Todo a { status = status }) todos + modifyAt i (\(Todo a) -> Todo a { status = status }) todos diff --git a/yarn.lock b/yarn.lock index 2fdb4d0..fbb634f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -326,10 +326,6 @@ arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1005,7 +1001,11 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" -bluebird@^3.3.5, bluebird@^3.5.1: +bluebird@^3.3.5: + version "3.5.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" + +bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -1557,10 +1557,6 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" -core-js@^1.0.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" - core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" @@ -1932,12 +1928,6 @@ encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" - end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -2242,18 +2232,6 @@ faye-websocket@~0.11.0: dependencies: websocket-driver ">=0.5.1" -fbjs@^0.8.16: - version "0.8.16" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" - dependencies: - core-js "^1.0.0" - isomorphic-fetch "^2.1.1" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.9" - feint@1.0.2, feint@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/feint/-/feint-1.0.2.tgz#f4ac51d6ed7db2cc5a0ba6913f84d43f72dd680b" @@ -2828,7 +2806,7 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@^0.4.17, iconv-lite@^0.4.4: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" dependencies: @@ -3216,7 +3194,7 @@ is-scoped@^1.0.0: dependencies: scoped-regex "^1.0.0" -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3258,13 +3236,6 @@ isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" -isomorphic-fetch@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" - istextorbinary@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" @@ -3354,7 +3325,7 @@ json3@^3.3.2: json5@^0.5.0, json5@^0.5.1: version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + resolved "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" junk@^2.1.0: version "2.1.0" @@ -3937,13 +3908,6 @@ node-dir@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d" -node-fetch@^1.0.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - node-forge@0.7.5: version "0.7.5" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" @@ -4385,7 +4349,7 @@ pbkdf2@^3.0.3: pify@^2.0.0, pify@^2.3.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + resolved "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" pify@^3.0.0: version "3.0.0" @@ -4486,17 +4450,10 @@ promise-retry@^1.1.0: err-code "^1.0.0" retry "^0.10.0" -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" +prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" dependencies: - asap "~2.0.3" - -prop-types@^15.6.0: - version "15.6.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" - dependencies: - fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" @@ -4583,8 +4540,8 @@ purescript@^0.12.0: install-purescript-cli "^0.4.0 || ^0.3.0" purs-loader@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/purs-loader/-/purs-loader-3.1.4.tgz#92a4326e748bdf7aff9d69f4a10feb8466e148a6" + version "3.2.0" + resolved "https://registry.yarnpkg.com/purs-loader/-/purs-loader-3.2.0.tgz#90dea335976fb87199f721969eaee95ad6810721" dependencies: bluebird "^3.3.5" chalk "^1.1.3" @@ -4670,23 +4627,23 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-dom@^16.0.0: - version "16.4.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.0.tgz#099f067dd5827ce36a29eaf9a6cdc7cbf6216b1e" +react-dom@^16.7.0-alpha.2: + version "16.7.0-alpha.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0-alpha.2.tgz#16632880ed43676315991d8b412cce6975a30282" dependencies: - fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.0" + prop-types "^15.6.2" + scheduler "^0.12.0-alpha.2" -react@^16.0.0: - version "16.4.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.4.0.tgz#402c2db83335336fba1962c08b98c6272617d585" +react@^16.7.0-alpha.2: + version "16.7.0-alpha.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.7.0-alpha.2.tgz#924f2ae843a46ea82d104a8def7a599fbf2c78ce" dependencies: - fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.0" + prop-types "^15.6.2" + scheduler "^0.12.0-alpha.2" read-chunk@^2.1.0: version "2.1.0" @@ -5014,6 +4971,13 @@ sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" +scheduler@^0.12.0-alpha.2: + version "0.12.0-alpha.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.12.0-alpha.2.tgz#2a8bc8dc6ecdb75fa6480ceeedc1f187c9539970" + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + schema-utils@^0.4.4, schema-utils@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e" @@ -5108,7 +5072,7 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4, setimmediate@^1.0.5: +setimmediate@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -5642,10 +5606,6 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -ua-parser-js@^0.7.9: - version "0.7.18" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" - uglify-es@^3.3.4: version "3.3.9" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" @@ -5994,10 +5954,6 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" -whatwg-fetch@>=0.10.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" From afd619c293cd6317bce6cd8f0efd2c062d3502de Mon Sep 17 00:00:00 2001 From: eric thul Date: Sat, 1 Dec 2018 10:22:20 -0500 Subject: [PATCH 2/5] Update example --- src/Example/TodoForm.purs | 20 +++++++++----------- src/Example/TodoItem.purs | 5 ++--- src/Example/TodoList.purs | 7 ++++--- src/Main.purs | 19 ++++++++++--------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/Example/TodoForm.purs b/src/Example/TodoForm.purs index f43ae08..04da3c5 100644 --- a/src/Example/TodoForm.purs +++ b/src/Example/TodoForm.purs @@ -2,13 +2,12 @@ module Example.TodoForm where import Prelude -import Effect (Effect) - import Data.Maybe (Maybe, maybe, isNothing) -import Data.Tuple (Tuple(..)) + +import Effect (Effect) import React as React -import React.Hooks as Hooks +import React.Hook (Hook) import React.SyntheticEvent as Event import React.DOM as DOM import React.DOM.Props as Props @@ -23,21 +22,20 @@ type TodoFormProps , onAdd :: Todo -> Effect Unit } -todoForm :: TodoFormProps -> Effect React.ReactElement +todoForm :: TodoFormProps -> Hook React.ReactElement todoForm { todo , onEdit , onAdd - } = render <$> Hooks.useState "" + } = pure render where - render (Tuple value setState) = + render = DOM.form [ Props.onSubmit onSubmit ] [ DOM.input [ Props._type "text" , Props.value value - --, Props.onChange onChange - , Props.onChange \event -> Hooks.setState setState (unsafeCoerce event).target.value + , Props.onChange onChange ] , DOM.button [ Props._type "submit" @@ -46,7 +44,7 @@ todoForm [ DOM.text "Add" ] ] where - value'' = maybe "" (\(Todo { text }) -> text) todo + value = maybe "" (\(Todo { text }) -> text) todo isDisabled = isNothing todo @@ -55,7 +53,7 @@ todoForm maybe (pure unit) onAdd todo - onChange'' event = onEdit $ + onChange event = onEdit $ maybe (Todo { text, status: TodoPending }) (\(Todo todo_) -> Todo todo_ { text = text }) todo diff --git a/src/Example/TodoItem.purs b/src/Example/TodoItem.purs index 16d5949..56e2dc3 100644 --- a/src/Example/TodoItem.purs +++ b/src/Example/TodoItem.purs @@ -2,9 +2,8 @@ module Example.TodoItem where import Prelude -import Effect (Effect) - import React as React +import React.Hook (Hook) import React.DOM as DOM import React.DOM.Props as Props @@ -12,7 +11,7 @@ import Example.Types (Todo(..), TodoStatus(..)) type TodoItemProps = { todo :: Todo } -todoItem :: TodoItemProps -> Effect React.ReactElement +todoItem :: TodoItemProps -> Hook React.ReactElement todoItem { todo: Todo { text diff --git a/src/Example/TodoList.purs b/src/Example/TodoList.purs index ff4ad20..4b4d37c 100644 --- a/src/Example/TodoList.purs +++ b/src/Example/TodoList.purs @@ -8,6 +8,7 @@ import Data.Array (filter) import Data.Maybe (Maybe) import React as React +import React.Hook (Hook) import React.DOM as DOM import React.DOM.Props as Props @@ -24,7 +25,7 @@ type TodoListProps , onClear :: Todo -> Effect Unit } -todoList :: TodoListProps -> Effect React.ReactElement +todoList :: TodoListProps -> Hook React.ReactElement todoList { todos , todo @@ -35,7 +36,7 @@ todoList } = pure $ DOM.div [ ] - [ React.createElementHooks todoForm + [ React.createElementHook todoForm { todo , onEdit , onAdd @@ -50,7 +51,7 @@ todoList renderItem todo' @ Todo { status } = DOM.li [ ] - [ React.createElementHooks todoItem { todo: todo' } + [ React.createElementHook todoItem { todo: todo' } , DOM.button [ Props._type "button" , Props.onClick onClick diff --git a/src/Main.purs b/src/Main.purs index 809573e..2ef1d98 100644 --- a/src/Main.purs +++ b/src/Main.purs @@ -16,7 +16,8 @@ import Web.HTML.Window (document) as DOM import Partial.Unsafe (unsafePartial) import React as React -import React.Hooks as Hooks +import React.Hook (Hook) +import React.Hook as Hook import ReactDOM as ReactDOM import Example.TodoList (todoList) @@ -36,10 +37,10 @@ main = void $ do let element' = unsafePartial (fromJust element) - ReactDOM.render (React.createElementHooks wrapper { }) element' + ReactDOM.render (React.createElementHook wrapper { }) element' -wrapper :: { } -> Effect React.ReactElement -wrapper _ = render <$> Hooks.useState initialState +wrapper :: { } -> Hook React.ReactElement +wrapper _ = render <$> Hook.useState initialState where initialState = { todo: Nothing @@ -51,24 +52,24 @@ wrapper _ = render <$> Hooks.useState initialState { todo , todos } setState) = - React.createElementHooks todoList + React.createElementHook todoList { todos , todo - , onAdd: \todo' -> Hooks.modifyState setState \a -> + , onAdd: \todo' -> Hook.modifyState setState \a -> a { todo = Nothing , todos = snoc a.todos todo' } - , onEdit: \todo' -> Hooks.modifyState setState + , onEdit: \todo' -> Hook.modifyState setState _ { todo = Just todo' } - , onDone: \todo' -> Hooks.modifyState setState \a -> + , onDone: \todo' -> Hook.modifyState setState \a -> a { todos = setStatus a.todos todo' TodoDone } - , onClear : \todo' -> Hooks.modifyState setState \a -> + , onClear : \todo' -> Hook.modifyState setState \a -> a { todos = setStatus a.todos todo' TodoCleared } } From 3c292238e591d89f6fdeaef2537398857f352d68 Mon Sep 17 00:00:00 2001 From: eric thul Date: Sun, 2 Dec 2018 09:46:00 -0500 Subject: [PATCH 3/5] Hook usage update --- src/Example.purs | 75 +++++++++++++++++++++++++++++++++++++++ src/Example/TodoList.purs | 4 +-- src/Main.purs | 51 ++------------------------ 3 files changed, 80 insertions(+), 50 deletions(-) create mode 100644 src/Example.purs diff --git a/src/Example.purs b/src/Example.purs new file mode 100644 index 0000000..7b76b7d --- /dev/null +++ b/src/Example.purs @@ -0,0 +1,75 @@ +module Example where + +import Prelude + +import Data.Array (snoc, modifyAt, elemIndex) +import Data.Maybe (Maybe(..), fromMaybe) +import Data.Tuple (Tuple(..)) + +import React as React +import React.Hook (Hook) +import React.Hook as Hook + +import Example.TodoList (todoList) +import Example.Types (Todo(..), TodoStatus(..)) + +data Action + = Add Todo + | Edit Todo + | Done Todo + | Clear Todo + +example :: { } -> Hook React.ReactElement +example _ = + React.createHookLeafElement todoList <$> hook + where + hook = do + Tuple state dispatch <- Hook.useReducer reducer initialState + + let + inputs = Just [ Hook.hookInput dispatch ] + + onAdd <- Hook.useCallback (Hook.dispatch dispatch <<< Add) inputs + + onEdit <- Hook.useCallback (Hook.dispatch dispatch <<< Edit) inputs + + onDone <- Hook.useCallback (Hook.dispatch dispatch <<< Done) inputs + + onClear <- Hook.useCallback (Hook.dispatch dispatch <<< Clear) inputs + + pure { todo: state.todo + , todos: state.todos + , onAdd + , onEdit + , onDone + , onClear + } + where + initialState = + { todo: Nothing + , todos: [ ] + } + + reducer state = + case _ of + Add todo -> state + { todo = Nothing + , todos = snoc state.todos todo + } + + Edit todo -> state + { todo = Just todo + } + + Done todo -> state + { todos = setStatus todo TodoDone + } + + Clear todo -> state + { todos = setStatus todo TodoCleared + } + where + setStatus todo status = fromMaybe state.todos $ do + i <- elemIndex todo state.todos + + modifyAt i (\(Todo a) -> Todo a { status = status }) state.todos diff --git a/src/Example/TodoList.purs b/src/Example/TodoList.purs index 4b4d37c..7a899f0 100644 --- a/src/Example/TodoList.purs +++ b/src/Example/TodoList.purs @@ -36,7 +36,7 @@ todoList } = pure $ DOM.div [ ] - [ React.createElementHook todoForm + [ React.createHookLeafElement todoForm { todo , onEdit , onAdd @@ -51,7 +51,7 @@ todoList renderItem todo' @ Todo { status } = DOM.li [ ] - [ React.createElementHook todoItem { todo: todo' } + [ React.createHookLeafElement todoItem { todo: todo' } , DOM.button [ Props._type "button" , Props.onClick onClick diff --git a/src/Main.purs b/src/Main.purs index 2ef1d98..433dd44 100644 --- a/src/Main.purs +++ b/src/Main.purs @@ -4,9 +4,7 @@ import Prelude import Effect (Effect) -import Data.Array (snoc, modifyAt, elemIndex) -import Data.Maybe (Maybe(..), fromJust, fromMaybe) -import Data.Tuple (Tuple(..)) +import Data.Maybe (fromJust) import Web.HTML.HTMLDocument (toNonElementParentNode) as DOM import Web.DOM.NonElementParentNode (getElementById) as DOM @@ -16,12 +14,9 @@ import Web.HTML.Window (document) as DOM import Partial.Unsafe (unsafePartial) import React as React -import React.Hook (Hook) -import React.Hook as Hook import ReactDOM as ReactDOM -import Example.TodoList (todoList) -import Example.Types (Todo(..), TodoStatus(..)) +import Example (example) main :: Effect Unit main = void $ do @@ -37,44 +32,4 @@ main = void $ do let element' = unsafePartial (fromJust element) - ReactDOM.render (React.createElementHook wrapper { }) element' - -wrapper :: { } -> Hook React.ReactElement -wrapper _ = render <$> Hook.useState initialState - where - initialState = - { todo: Nothing - , todos: [] - } - - render - (Tuple - { todo - , todos - } setState) = - React.createElementHook todoList - { todos - , todo - - , onAdd: \todo' -> Hook.modifyState setState \a -> - a { todo = Nothing - , todos = snoc a.todos todo' - } - - , onEdit: \todo' -> Hook.modifyState setState - _ { todo = Just todo' - } - - , onDone: \todo' -> Hook.modifyState setState \a -> - a { todos = setStatus a.todos todo' TodoDone - } - - , onClear : \todo' -> Hook.modifyState setState \a -> - a { todos = setStatus a.todos todo' TodoCleared - } - } - - setStatus todos todo status = fromMaybe todos $ do - i <- elemIndex todo todos - - modifyAt i (\(Todo a) -> Todo a { status = status }) todos + ReactDOM.render (React.createHookLeafElement example { }) element' From ff530bb097cf2d0c4da5fe18bd0aa9d966237823 Mon Sep 17 00:00:00 2001 From: eric thul Date: Sat, 8 Dec 2018 17:24:49 -0500 Subject: [PATCH 4/5] Add context and ref examples --- src/Example/TodoContext.purs | 11 +++++++++++ src/Example/TodoForm.js | 7 +++++++ src/Example/TodoForm.purs | 33 ++++++++++++++++++++++++++++++--- src/Example/TodoItem.purs | 15 ++++++++++++--- src/Example/TodoList.purs | 11 +++++++++-- 5 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 src/Example/TodoContext.purs create mode 100644 src/Example/TodoForm.js diff --git a/src/Example/TodoContext.purs b/src/Example/TodoContext.purs new file mode 100644 index 0000000..c394120 --- /dev/null +++ b/src/Example/TodoContext.purs @@ -0,0 +1,11 @@ +module Example.TodoContext where + +import Data.Maybe (Maybe(..)) + +import React.Context (Context) +import React.Context as Context + +type TodoContext = Context { backgroundColor :: String } + +todoContext :: TodoContext +todoContext = Context.createContext { backgroundColor: "red" } Nothing diff --git a/src/Example/TodoForm.js b/src/Example/TodoForm.js new file mode 100644 index 0000000..67d65de --- /dev/null +++ b/src/Example/TodoForm.js @@ -0,0 +1,7 @@ +'use strict'; + +exports.blur = function blur(ref) { + return function () { + return ref.blur(); + }; +} diff --git a/src/Example/TodoForm.purs b/src/Example/TodoForm.purs index 04da3c5..c510c71 100644 --- a/src/Example/TodoForm.purs +++ b/src/Example/TodoForm.purs @@ -2,18 +2,22 @@ module Example.TodoForm where import Prelude -import Data.Maybe (Maybe, maybe, isNothing) +import Data.Maybe (Maybe(..), maybe, isNothing) import Effect (Effect) import React as React import React.Hook (Hook) +import React.Hook as Hook +import React.Ref (Ref, DOMRef) +import React.Ref as Ref import React.SyntheticEvent as Event import React.DOM as DOM import React.DOM.Props as Props import Unsafe.Coerce (unsafeCoerce) +import Example.TodoContext as TodoContext import Example.Types (Todo(..), TodoStatus(..)) type TodoFormProps @@ -27,15 +31,30 @@ todoForm { todo , onEdit , onAdd - } = pure render + } = + render <$> hook where - render = + hook = do + context <- Hook.useContext TodoContext.todoContext + + ref <- Hook.useRef Nothing + + pure { ref, context } + + render + { ref + , context: + { backgroundColor + } + } = DOM.form [ Props.onSubmit onSubmit ] [ DOM.input [ Props._type "text" , Props.value value + , Props.ref ref , Props.onChange onChange + , Props.style { backgroundColor } ] , DOM.button [ Props._type "submit" @@ -53,9 +72,17 @@ todoForm maybe (pure unit) onAdd todo + domRef <- Ref.getRef ref + + maybe (pure unit) blur domRef + + pure unit + onChange event = onEdit $ maybe (Todo { text, status: TodoPending }) (\(Todo todo_) -> Todo todo_ { text = text }) todo where text = (unsafeCoerce event).target.value + +foreign import blur :: DOMRef -> Effect Unit diff --git a/src/Example/TodoItem.purs b/src/Example/TodoItem.purs index 56e2dc3..3f7b70f 100644 --- a/src/Example/TodoItem.purs +++ b/src/Example/TodoItem.purs @@ -3,10 +3,12 @@ module Example.TodoItem where import Prelude import React as React +import React.Context as Context import React.Hook (Hook) import React.DOM as DOM import React.DOM.Props as Props +import Example.TodoContext as TodoContext import Example.Types (Todo(..), TodoStatus(..)) type TodoItemProps = { todo :: Todo } @@ -18,10 +20,17 @@ todoItem , status } } = pure $ - DOM.div - [ Props.style { textDecoration } ] - [ React.toElement text ] + React.createRenderPropsElement consumer { } $ \{ backgroundColor } -> + DOM.div + [ Props.style + { textDecoration + , backgroundColor + } + ] + [ React.toElement text ] where + consumer = Context.getConsumer TodoContext.todoContext + textDecoration = case status of TodoDone -> "line-through" diff --git a/src/Example/TodoList.purs b/src/Example/TodoList.purs index 7a899f0..f84ef0c 100644 --- a/src/Example/TodoList.purs +++ b/src/Example/TodoList.purs @@ -8,10 +8,12 @@ import Data.Array (filter) import Data.Maybe (Maybe) import React as React +import React.Context as Context import React.Hook (Hook) import React.DOM as DOM import React.DOM.Props as Props +import Example.TodoContext as TodoContext import Example.TodoForm (todoForm) import Example.TodoItem (todoItem) import Example.Types (Todo(..), TodoStatus(..)) @@ -34,8 +36,11 @@ todoList , onDone , onClear } = pure $ - DOM.div - [ ] + React.createElement provider + { value: + { backgroundColor: "lightblue" + } + } [ React.createHookLeafElement todoForm { todo , onEdit @@ -46,6 +51,8 @@ todoList (renderItem <$> todos') ] where + provider = Context.getProvider TodoContext.todoContext + todos' = filter (\(Todo { status }) -> TodoCleared /= status) todos renderItem todo' @ Todo { status } = From b97f77877d11c79c47e37b4b1e7a97868acad536 Mon Sep 17 00:00:00 2001 From: eric thul Date: Sat, 8 Dec 2018 17:27:40 -0500 Subject: [PATCH 5/5] Use HTMLElement --- src/Example/TodoForm.js | 7 ------- src/Example/TodoForm.purs | 7 +++---- 2 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 src/Example/TodoForm.js diff --git a/src/Example/TodoForm.js b/src/Example/TodoForm.js deleted file mode 100644 index 67d65de..0000000 --- a/src/Example/TodoForm.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -exports.blur = function blur(ref) { - return function () { - return ref.blur(); - }; -} diff --git a/src/Example/TodoForm.purs b/src/Example/TodoForm.purs index c510c71..db81e40 100644 --- a/src/Example/TodoForm.purs +++ b/src/Example/TodoForm.purs @@ -9,12 +9,13 @@ import Effect (Effect) import React as React import React.Hook (Hook) import React.Hook as Hook -import React.Ref (Ref, DOMRef) import React.Ref as Ref import React.SyntheticEvent as Event import React.DOM as DOM import React.DOM.Props as Props +import Web.HTML.HTMLElement as HTML + import Unsafe.Coerce (unsafeCoerce) import Example.TodoContext as TodoContext @@ -74,7 +75,7 @@ todoForm domRef <- Ref.getRef ref - maybe (pure unit) blur domRef + maybe (pure unit) (HTML.blur <<< unsafeCoerce) domRef pure unit @@ -84,5 +85,3 @@ todoForm todo where text = (unsafeCoerce event).target.value - -foreign import blur :: DOMRef -> Effect Unit pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy