1
1
module React.Router.Components
2
2
( browserRouter
3
3
, browserRouterClass
4
+ , LinkProps (LinkProps)
4
5
, linkSpec
5
6
, link
6
7
, link'
7
- , to
8
- , goTo
8
+ , goto
9
9
) where
10
10
11
11
@@ -25,11 +25,11 @@ import DOM.HTML.Types (HISTORY, windowToEventTarget)
25
25
import DOM.HTML.Window (history , location )
26
26
import Data.Foreign (toForeign )
27
27
import Data.List (List )
28
- import Data.Maybe (Maybe (..), fromMaybe , isNothing , maybe' )
28
+ import Data.Maybe (Maybe (..), fromMaybe , isNothing , maybe , maybe ' )
29
29
import Data.Newtype (un )
30
30
import Data.Tuple (Tuple )
31
31
import Prelude (Unit , bind , const , discard , pure , show , unit , void , ($), (<<<), (<>), (>>=), (||))
32
- import React (ReactClass , ReactElement , ReactSpec , createClass , createElement , getChildren , getProps , preventDefault , readState , spec , spec' , transformState )
32
+ import React (ReactClass , ReactElement , ReactProps , ReactRefs , ReactSpec , ReactState , ReadOnly , ReadWrite , createClass , createElement , getChildren , getProps , preventDefault , readState , spec , spec' , transformState )
33
33
import React.DOM (a , div' )
34
34
import React.DOM.Props (Props , href , onClick )
35
35
import React.Router.Class (class RoutePropsClass )
@@ -40,7 +40,7 @@ import React.Router.Utils (hasBaseName, joinUrls, stripBaseName, warning)
40
40
-- | RouterState type
41
41
type RouterState =
42
42
{ hash :: String
43
- , pathname :: String
43
+ , pathname :: URL
44
44
, search :: String
45
45
}
46
46
@@ -53,23 +53,23 @@ type RouterProps props arg notFoundProps =
53
53
}
54
54
}
55
55
56
- foreign import createPopStateEvent :: String -> Event
56
+ foreign import createPopStateEvent :: URL -> Event
57
57
58
58
getLocation
59
59
:: forall e
60
60
. RouterConfig
61
- -> Eff (dom :: DOM , console :: CONSOLE | e ) { hash :: String , pathname :: String , search :: String }
61
+ -> Eff (dom :: DOM , console :: CONSOLE | e ) { hash :: String , pathname :: URL , search :: String }
62
62
getLocation cfg = do
63
63
l <- window >>= location
64
64
h <- hash l
65
65
p <- pathname l
66
66
s <- search l
67
67
let cfgR = un RouterConfig cfg
68
68
warning
69
- (isNothing cfgR.baseName || (hasBaseName cfgR.baseName p ))
69
+ (isNothing cfgR.baseName || (hasBaseName cfgR.baseName ( URL p) ))
70
70
(""" You are using baseName on a page which URL path does not begin with. Expecting path: """
71
- <> p <> """ to begin with: """ <> (fromMaybe " " cfgR.baseName))
72
- pure { hash: h, pathname: stripBaseName cfgR.baseName p , search: s }
71
+ <> p <> """ to begin with: """ <> (maybe " " (un URL ) cfgR.baseName))
72
+ pure { hash: h, pathname: stripBaseName cfgR.baseName ( URL p) , search: s }
73
73
74
74
75
75
-- | `ReactSpec` for the `browserRouterClass` - the main entry point react
@@ -90,7 +90,7 @@ browserRouter cfg = (spec' initialState render) { displayName = "BrowserRouter",
90
90
render this = do
91
91
props <- getProps this
92
92
state <- readState this
93
- let loc = state.pathname <> state.search <> state.hash
93
+ let loc = un URL state.pathname <> state.search <> state.hash
94
94
95
95
case runRouter loc props.router of
96
96
Nothing -> do
@@ -121,57 +121,60 @@ browserRouterClass
121
121
-> ReactClass (RouterProps props arg notfound )
122
122
browserRouterClass cfg = createClass (browserRouter cfg)
123
123
124
- type LinkProps = { to :: String , props :: Array Props }
125
-
126
- to :: String -> LinkProps
127
- to = { to: _, props: [] }
124
+ newtype LinkProps eff = LinkProps
125
+ { url :: URL
126
+ , props :: Array Props
127
+ , action :: Eff (props :: ReactProps , refs :: ReactRefs ReadOnly , state :: ReactState ReadWrite | eff ) Unit
128
+ }
128
129
129
130
-- | `ReactSpec` for the `link` element; it takes a record of type `LinkProps`
130
131
-- | as properties. The `props` record property is directly passed to underlying
131
132
-- | `a` element, e.g. this can be used to add css classes.
132
- linkSpec :: RouterConfig -> ReactSpec LinkProps Unit ()
133
- linkSpec cfg = (spec unit render) { displayName = " Link" }
133
+ linkSpec :: forall eff . ReactSpec ( LinkProps eff ) Unit ()
134
+ linkSpec = (spec unit render) { displayName = " Link" }
134
135
where
135
136
render this = do
136
- p <- getProps this
137
+ LinkProps p <- getProps this
137
138
chrn <- getChildren this
138
139
pure $ a
139
- ([href p.to , (onClick $ clickHandler this)] <> p.props)
140
+ ([href (un URL p.url) , (onClick $ clickHandler this)] <> p.props)
140
141
chrn
141
142
142
143
clickHandler this ev = do
143
144
_ <- preventDefault ev
144
- { to: url } <- getProps this
145
- goTo cfg url
145
+ LinkProps { action } <- getProps this
146
+ action
146
147
147
148
-- | React class for the `link` element.
148
- linkClass :: RouterConfig -> ReactClass LinkProps
149
- linkClass = createClass <<< linkSpec
149
+ linkClass :: forall eff . ReactClass ( LinkProps eff )
150
+ linkClass = createClass linkSpec
150
151
151
- -- | `link` element; use it instead of `a` to route the user through application.
152
- link :: RouterConfig -> LinkProps -> Array ReactElement -> ReactElement
153
- link cfg = createElement (linkClass cfg)
152
+ -- | `link` element; use it instead of `a` to route the user through
153
+ -- | application with the default action `goto cfg url` and custom properties.
154
+ link :: RouterConfig -> URL -> Array Props -> Array ReactElement -> ReactElement
155
+ link cfg url props = createElement linkClass (LinkProps { url, props, action: goto cfg url})
154
156
155
- -- | as `link`, but with empty properties passed to the underlying `a` element .
156
- link' :: RouterConfig -> String -> Array ReactElement -> ReactElement
157
- link' cfg = link cfg <<< {to: _, props: [] }
157
+ -- | as `link`, but with empty props .
158
+ link' :: RouterConfig -> URL -> Array ReactElement -> ReactElement
159
+ link' cfg url = link cfg url []
158
160
159
- goTo
161
+ -- | goto url
162
+ goto
160
163
:: forall eff
161
164
. RouterConfig
162
- -> String
165
+ -> URL
163
166
-> Eff ( console :: CONSOLE
164
167
, dom :: DOM
165
168
, history :: HISTORY
166
169
| eff
167
170
) Unit
168
- goTo cfg url = catchException
171
+ goto cfg url = catchException
169
172
(error <<< show)
170
173
(do
171
174
w <- window
172
175
h <- history w
173
- let url_ = joinUrls (fromMaybe " " (un RouterConfig cfg).baseName) url
174
- pushState (toForeign unit) (DocumentTitle url_) ( URL url_) h
176
+ let url_ = joinUrls (fromMaybe ( URL " " ) (un RouterConfig cfg).baseName) url
177
+ pushState (toForeign unit) (DocumentTitle (un URL url_)) url_ h
175
178
void $ coerceEff $ dispatchEvent (createPopStateEvent url) (windowToEventTarget w))
176
179
where
177
180
coerceEff :: forall e a . Eff (err :: EXCEPTION | e ) a -> Eff (exception :: EXCEPTION | e ) a
0 commit comments