Skip to content

Commit 5161ed1

Browse files
author
Michael Trotter
committed
Add Compat module; fix stateless; build docs
1 parent 5cf3975 commit 5161ed1

15 files changed

Lines changed: 504 additions & 93 deletions

File tree

examples/legacy-v2/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output
2+
html/index.js
3+
package-lock.json
4+
node_modules

examples/legacy-v2/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
all: node_modules
2+
purs compile src/*.purs '../../src/**/*.purs' '../../bower_components/purescript-*/src/**/*.purs'
3+
purs bundle -m Main --main Main output/*/*.js > output/bundle.js
4+
node_modules/.bin/browserify output/bundle.js -o html/index.js
5+
6+
node_modules:
7+
npm install
8+

examples/legacy-v2/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Counter Example
2+
3+
## Building
4+
5+
```
6+
npm install
7+
make all
8+
```
9+
10+
This will compile the PureScript source files, bundle them, and use Browserify to combine PureScript and NPM sources into a single bundle.
11+
12+
Then open `html/index.html` in your browser.

examples/legacy-v2/html/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>react-basic example</title>
5+
</head>
6+
<body>
7+
<div id="container"></div>
8+
<script src="index.js"></script>
9+
</body>
10+
</html>

examples/legacy-v2/package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"dependencies": {
3+
"react": "^16.4.2",
4+
"react-dom": "^16.4.2"
5+
},
6+
"devDependencies": {
7+
"browserify": "^16.2.2"
8+
}
9+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module LegacyCounter where
2+
3+
import Prelude
4+
5+
import React.Basic.Compat (Component, component, element, stateless)
6+
import React.Basic.DOM as R
7+
import React.Basic.Events as Events
8+
9+
type Props =
10+
{ label :: String
11+
}
12+
13+
-- | checks `component`
14+
counter :: Component Props
15+
counter = component { displayName: "LegacyCounter", initialState, receiveProps, render }
16+
where
17+
initialState =
18+
{ counter: 0
19+
}
20+
21+
receiveProps self =
22+
pure unit
23+
24+
render self =
25+
R.button
26+
{ onClick: Events.handler_ do
27+
self.setState \s -> s { counter = s.counter + 1 }
28+
, children: [ element buttonLabel { label: self.props.label, counter: self.state.counter } ]
29+
}
30+
31+
-- | checks `stateless`
32+
buttonLabel :: Component { label :: String, counter :: Int }
33+
buttonLabel = stateless { displayName: "ButtonLabel", render }
34+
where
35+
render props =
36+
R.text (props.label <> ": " <> show props.counter)

examples/legacy-v2/src/Main.purs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Main where
2+
3+
import Prelude
4+
5+
import Data.Maybe (Maybe(..))
6+
import Effect (Effect)
7+
import Effect.Exception (throw)
8+
import LegacyCounter as LegacyCounter
9+
import React.Basic (element)
10+
import React.Basic.DOM (render)
11+
import Web.DOM.NonElementParentNode (getElementById)
12+
import Web.HTML (window)
13+
import Web.HTML.HTMLDocument (toNonElementParentNode)
14+
import Web.HTML.Window (document)
15+
16+
main :: Effect Unit
17+
main = do
18+
container <- getElementById "container" =<< (map toNonElementParentNode $ document =<< window)
19+
case container of
20+
Nothing -> throw "Container element not found."
21+
Just c ->
22+
let app = element LegacyCounter.counter { label: "Increment" }
23+
in render app c

generated-docs/React/Basic.md

Lines changed: 133 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33
#### `Component`
44

55
``` purescript
6-
data Component :: Type -> Type
6+
type Component = forall props state action. ComponentSpec props state action
77
```
88

9-
A React component which can be used from JavaScript.
10-
11-
#### `ComponentInstance`
9+
#### `StatelessComponent`
1210

1311
``` purescript
14-
data ComponentInstance :: Type
12+
type StatelessComponent = forall props. ComponentSpec props Void Void
1513
```
1614

17-
Represents the mounted component instance, or "this" in vanilla React.
15+
#### `ComponentSpec`
16+
17+
``` purescript
18+
type ComponentSpec props state action = { "$$type" :: ReactComponent props, initialState :: state, shouldUpdate :: LimitedSelf props state -> props -> state -> Boolean, didMount :: Self props state action -> Effect Unit, didUpdate :: Self props state action -> Effect Unit, willUnmount :: LimitedSelf props state -> Effect Unit, update :: Update props state action, render :: Self props state action -> JSX }
19+
```
1820

1921
#### `JSX`
2022

@@ -30,51 +32,123 @@ Semigroup JSX
3032
Monoid JSX
3133
```
3234

33-
#### `component`
35+
#### `Update`
3436

3537
``` purescript
36-
component :: forall props state. { displayName :: String, initialState :: { | state }, receiveProps :: { isFirstMount :: Boolean, props :: { | props }, state :: { | state }, setState :: SetState state, setStateThen :: SetStateThen state, instance_ :: ComponentInstance } -> Effect Unit, render :: { props :: { | props }, state :: { | state }, setState :: SetState state, setStateThen :: SetStateThen state, instance_ :: ComponentInstance } -> JSX } -> Component { | props }
38+
type Update props state action = Self props state action -> action -> StateUpdate props state action
3739
```
3840

39-
Create a React component from a _specification_ of that component.
41+
#### `StateUpdate`
4042

41-
A _specification_ consists of a state type, an initial value for that state,
42-
a function to apply incoming props to the internal state, and a rendering
43-
function which takes props, state and a state update function.
43+
``` purescript
44+
data StateUpdate props state action
45+
= NoUpdate
46+
| Update state
47+
| SideEffects (Self props state action -> Effect Unit)
48+
| UpdateAndSideEffects state (Self props state action -> Effect Unit)
49+
```
4450

45-
The rendering function should return a value of type `JSX`, which can be
46-
constructed using the helper functions provided by the `React.Basic.DOM`
47-
module.
51+
#### `Self`
4852

49-
Note: This function relies on `React.PureComponent` internally
53+
``` purescript
54+
type Self props state action = { props :: props, state :: state, readProps :: Effect props, readState :: Effect state, send :: action -> Effect Unit, instance_ :: ReactComponentInstance }
55+
```
5056

51-
#### `stateless`
57+
#### `LimitedSelf`
5258

5359
``` purescript
54-
stateless :: forall props. { displayName :: String, render :: { | props } -> JSX } -> Component { | props }
60+
type LimitedSelf props state = { props :: props, state :: state }
5561
```
5662

57-
Create a stateless React component.
63+
#### `ReactComponent`
5864

59-
Removes a little bit of the `react` function's boilerplate when creating
60-
components which don't use state.
65+
``` purescript
66+
data ReactComponent props
67+
```
6168

62-
#### `element`
69+
#### `ReactComponentInstance`
6370

6471
``` purescript
65-
element :: forall props. Component { | props } -> { | props } -> JSX
72+
data ReactComponentInstance
6673
```
6774

68-
Create a `JSX` node from a React component, by providing the props.
75+
#### `make`
6976

70-
#### `elementKeyed`
77+
``` purescript
78+
make :: forall props state action. ComponentSpec props state action -> props -> JSX
79+
```
80+
81+
Turn a `ComponentSpec` into a usable render function.
82+
This is usually where you will want to provide customized
83+
implementations:
84+
85+
```purs
86+
type Props =
87+
{ label :: String
88+
}
89+
90+
data Action
91+
= Increment
92+
93+
render :: Props -> JSX
94+
render = make component
95+
{ initialState = { counter: 0 }
96+
97+
, update = \self action -> case action of
98+
Increment ->
99+
Update self.state { counter = self.state.counter + 1 }
100+
101+
, render = \self ->
102+
R.button
103+
{ onClick: Events.handler_ do self.send Increment
104+
, children: [ R.text (self.props.label <> ": " <> show self.state.counter) ]
105+
}
106+
}
107+
108+
component :: Component
109+
component = createComponent "Counter"
110+
```
111+
112+
#### `makeStateless`
71113

72114
``` purescript
73-
elementKeyed :: forall props. Component { | props } -> { key :: String | props } -> JSX
115+
makeStateless :: forall props. ComponentSpec props Void Void -> (props -> JSX) -> props -> JSX
74116
```
75117

76-
Like `element`, plus a `key` for rendering components in a dynamic list.
77-
For more information see: https://reactjs.org/docs/reconciliation.html#keys
118+
Helper to make stateless component definition slightly
119+
less verbose:
120+
121+
```purs
122+
render = makeStateless component \props -> JSX
123+
124+
component = createStatelessComponent "Xyz"
125+
```
126+
127+
#### `asyncEffects`
128+
129+
``` purescript
130+
asyncEffects :: forall props state action. (Self props state action -> Aff action) -> Self props state action -> Effect Unit
131+
```
132+
133+
Convenience function for sending an action asynchronously.
134+
135+
Note: potential failure should be handled and converted to an
136+
action, as the default error handler will simply log the
137+
error to the console.
138+
139+
#### `createComponent`
140+
141+
``` purescript
142+
createComponent :: String -> { "$$type" :: forall props. ReactComponent props, initialState :: forall state. state, shouldUpdate :: forall props state. LimitedSelf props state -> props -> state -> Boolean, didMount :: forall props state action. Self props state action -> Effect Unit, didUpdate :: forall props state action. Self props state action -> Effect Unit, willUnmount :: forall props state action. LimitedSelf props state -> Effect Unit, update :: forall props state action. Update props state action, render :: forall props state action. Self props state action -> JSX }
143+
```
144+
145+
#### `createStatelessComponent`
146+
147+
``` purescript
148+
createStatelessComponent :: String -> { "$$type" :: forall props. ReactComponent props, initialState :: Void, shouldUpdate :: forall props. LimitedSelf props Void -> props -> Void -> Boolean, didMount :: forall props. Self props Void Void -> Effect Unit, didUpdate :: forall props. Self props Void Void -> Effect Unit, willUnmount :: forall props. LimitedSelf props Void -> Effect Unit, update :: forall props. Update props Void Void, render :: forall props. Self props Void Void -> JSX }
149+
```
150+
151+
Creates a named, stateless component
78152

79153
#### `empty`
80154

@@ -86,6 +160,14 @@ An empty node. This is often useful when you would like to conditionally
86160
show something, but you don't want to (or can't) modify the `children` prop
87161
on the parent node.
88162

163+
#### `keyed`
164+
165+
``` purescript
166+
keyed :: String -> JSX -> JSX
167+
```
168+
169+
Apply a React key to a sub-tree.
170+
89171
#### `fragment`
90172

91173
``` purescript
@@ -105,4 +187,27 @@ Render an Array of children without a wrapping component.
105187
Provide a key when dynamically rendering multiple fragments along side
106188
each other.
107189

190+
#### `element`
191+
192+
``` purescript
193+
element :: forall props. ReactComponent { | props } -> { | props } -> JSX
194+
```
195+
196+
Create a `JSX` node from a React component, by providing the props.
197+
198+
#### `elementKeyed`
199+
200+
``` purescript
201+
elementKeyed :: forall props. ReactComponent { | props } -> { key :: String | props } -> JSX
202+
```
203+
204+
Like `element`, plus a `key` for rendering components in a dynamic list.
205+
For more information see: https://reactjs.org/docs/reconciliation.html#keys
206+
207+
#### `toReactComponent`
208+
209+
``` purescript
210+
toReactComponent :: forall props. ({ | props } -> JSX) -> ReactComponent { | props }
211+
```
212+
108213

0 commit comments

Comments
 (0)