Skip to content

Instantly share code, notes, and snippets.

@thangngoc89
Created February 22, 2018 08:11
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thangngoc89/c9162c0263df5427fe9a36fc7f94ac94 to your computer and use it in GitHub Desktop.
Save thangngoc89/c9162c0263df5427fe9a36fc7f94ac94 to your computer and use it in GitHub Desktop.
Reason React Router example
let component = ReasonReact.statelessComponent("App");
let make = _children => {
...component,
render: _self =>
<LayoutGrid>
<Router.WithRouter>
...(
(~currentRoute) =>
switch currentRoute {
| Dashboard => <Loadable_Dashboard_Route />
| PatientList => <Loadable_PatientList_Route />
| PatientDetail(id) => <Loadable_PatientDetail_Route id />
| _ => "Not found" |> text
}
)
</Router.WithRouter>
</LayoutGrid>
};
type routes =
| Dashboard
| PatientList
| PatientDetail(string)
| Appointment
| Setting
| NotFound;
let routeToString =
fun
| Dashboard => "/"
| PatientList => "/patient/list"
| PatientDetail(id) => "/patient/detail/" ++ id
| Appointment => "/appointments"
| Setting => "/settings"
| NotFound => "/404";
let urlToRoute: ReasonReact.Router.url => routes =
url =>
switch url.path {
| [] => Dashboard
| ["patient", "list"] => PatientList
| ["patient", "detail", id] => PatientDetail(id)
| ["appointments"] => Appointment
| ["settings"] => Setting
| _ => NotFound
};
<Router.NavLink
route=node.route
className=s##menuEntry
activeClassName=s##menuEntryActive
activeRoute=node.route>
<Icon type_=node.icon />
<span> (node.title |> text) </span>
</Router.NavLink>
module WithRouter = {
type state = {currentRoute: Config.routes};
type action =
| ChangeUrl(Config.routes);
let component = ReasonReact.reducerComponent("WithRouter");
let make:
((~currentRoute: Config.routes) => ReasonReact.reactElement) =>
ReasonReact.component(state, _, action) =
children => {
...component,
initialState: () => {
currentRoute:
ReasonReact.Router.dangerouslyGetInitialUrl() |> Config.urlToRoute
},
reducer: (action, _state) =>
switch action {
| ChangeUrl(route) => ReasonReact.Update({currentRoute: route})
},
subscriptions: ({send}) => [
Sub(
() =>
ReasonReact.Router.watchUrl(url =>
send(ChangeUrl(url |> Config.urlToRoute))
),
ReasonReact.Router.unwatchUrl
)
],
render: ({state}) => children(~currentRoute=state.currentRoute)
};
};
module Link = {
let component = ReasonReact.statelessComponent("Link");
let make = (~route, ~className="", children) => {
...component,
render: self => {
let href = Config.routeToString(route);
ReasonReact.createDomElement(
"a",
~props={
"className": className,
"href": href,
"onClick":
self.handle((event, _self) => {
ReactEventRe.Mouse.preventDefault(event);
ReasonReact.Router.push(href);
})
},
children
);
}
};
};
module NavLink = {
let component = ReasonReact.statelessComponent("NavLink");
let make = (~route, ~activeRoute=?, ~activeClassName, ~className=?, children) => {
...component,
render: _self =>
<WithRouter>
...(
(~currentRoute) => {
let activeRoute =
switch activeRoute {
| None => route
| Some(route) => route
};
let className =
Cn.make([
Cn.ifOpt(className),
Cn.ifBool(activeRoute == currentRoute, activeClassName)
]);
<Link route className> ...children </Link>;
}
)
</WithRouter>
};
};
@malisbad
Copy link

malisbad commented Mar 5, 2018

@persianturtle
Copy link

It looks like the API for Cn has changed.

In the NavLink module, changing this:

let className =
  Cn.make([
    Cn.ifOpt(className),
    Cn.ifBool(activeRoute == currentRoute, activeClassName)
  ]);

to:

let className =
  Cn.make([
    Cn.unwrap(className),
    Cn.ifTrue(activeRoute == currentRoute, activeClassName),
  ]);

works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment