Using "routing" with react (no halogen)

Does anyone have a working, simple example of doing routing with the routing library and react-basic-hooks? I found this post but it’s not complete and as a beginner, I frankly don’t get it.
Naively, I would’ve guessed routing is just parsing the URL hash and selecting a component based off it, but the type of matches matches :: forall a. Match a -> (Maybe a -> a -> Effect Unit) -> Effect (Effect Unit) is very much removed from react, so I’m a little intimidated here. Also, most of the stuff you find is using halogen, which I’m not using. I also saw the real world purescript react example, but that one is even less helpful because it’s too big and is using more libraries.
Can anyone help?

Maybe this recipe helps?

Sadly, this example is a bit too minimal. It doesn’t use React.

Thanks for checking out my real world purescript react example. It’s uses purescript-wire-react-router. That liberary has a small example that you might find useful:

Thanks, but then I’d have to learn about wire (which doesn’t even have a Readme?), wire-react and then about routing. It’s seems like quite a detour.

I put together a small example just using routing and react-basic-hooks here: https://try.purescript.org/?gist=1c5c2f222f723acefae637df3f6df721. (Pretty much lifted the example from the routing docs here.)

I think using hash-based routing (as this example does) from Routing.Hash is probably quite a bit simpler than using the Routing.PushState module. I think to use the latter you’d have to wrap your app in a Context that provides the PushStateInterface and then have special link components (in place of anchor tags) that call pushState (which they could get from useContext). At least that’s how I imagine it could work.

This is my first attempt at routing with PureScript + React so there’s probably room for improvement :slight_smile:.

routing-duplex would also get you some more type safety (in my simple example, I’m just matching string hrefs with strings in the appRoute function, which is error-prone).

1 Like

I just push up a README for Wire if that helps.

wire-react-router returns a Signal of the current route, and the useSignal hook from wire-react is only used for connecting the route signal to the React component. You could skip wire-react entirely tbh.

1 Like

I actually went a step further, and separated wire-react-router (v0.2.0) so it no longer depends on wire at all. Bring your own state management.

3 Likes

Thanks, but the link seems to be dead?

I also updated Real World example to use v0.2.1

1 Like

To go back to your opening post, if you’re having trouble with the types and you are using the hash-based part of the library we can try to break it down for you.

Starting with:
matches :: forall a. Match a -> (Maybe a -> a -> Effect Unit) -> Effect (Effect Unit)

Here, the a is a placeholder for the type you will be using to represent your routes in the application.

Match a is an applicative DSL modelling a string-based parser that tries to match the new path and produce one of your custom route values.

(Maybe a -> a -> Effect Unit) is a function that will receive the previous route if it exists (Maybe a), the new route based on your parser and the Effect Unit is whatever you need it to be in order to handle the new route (store it in React state, write it to a signal, etc).

Finally, the Effect (Effect Unit) is describing a subscription. Performing the outer effect will subscribe this logic to hash changes, and the inner Effect Unit it returns can be run at any later point to cancel the subscription.

Maybe you can see a bit more of the meaning with matchesWith:
matchesWith :: forall f a. Foldable f => (String -> f a) → (Maybe a -> a -> Effect Unit) -> Effect (Effect Unit)
where the first function is more clearly a string parser producing some route a.

1 Like

So assuming you already have your parser, the simplest example would be:

-- assumed
routes :: Match MyRoute
initialRoute :: MyRoute

myRouter =
  React.component "MyRouter" \props -> React.do
    route /\ setRoute <- React.useState' initialRoute
    React.useEffectOnce do
      cancel <- matches routes \maybeOldRoute newRoute -> setRoute newRoute
      pure cancel
    ... -- do whatever you want with `route` here
1 Like

Hm, the link works for me, does it not land on TryPureScript? The route defaults to the “Not found” route which could be improved but there should still be links in the right pane for Home / Posts. In any case the gist is here: https://gist.github.com/ptrfrncsmrph/1c5c2f222f723acefae637df3f6df721

1 Like

I want to only add that I’m a happy user of the purescript-wire-react-router (I’ve migrated from my own non hooks based API) and from my perspective this solution exposes a really nice hook based API. If you don’t care about route transitions you can just use _Route lens when dispatching a new route. Provided example is also quite easy to adapt.

2 Likes

This project uses wire/routing-duplex/react as well: https://github.com/jonasbuntinx/purescript-react-realworld