0

I have several panels defined for my app like so:

(defmulti panels identity)
(defmethod panels :panel1 [] [panel1])
(defmethod panels :panel2 [] [panel2])
(defmethod panels :panel3 [] [panel3])

I can use bidi+pushy in the client side to push a route, say /panel1-uri when an event (click in this case) occurs and change the panel using dispatch. But when I access localhost:5000/panel1-uri directly through the browser, this doesn't work since the /panel1-uri route doesn't exist in the server.

So I create a route in my server /panel1-uri, that just serves index.html and add the key of the panel I want to show in the header of this route's response. Then I create an anchor href to localhost:5000/panel1-uri rather than dispatching an event (to push /panel1-uri), but of course, this still serves the default panel. However, the response I have received from clicking href does contain the correct panel key in its header. How can I access this header I received from the response after clicking href and use it to change the panel?

Alternatively, Is there a better way to approach the problem of serving uri's that not only work with events in the client-side but also when entered directly into the browser?

zengod
  • 1,114
  • 13
  • 26

1 Answers1

1

I solved this issue in a similar way as you did:

  • one route /pannel-1 => index.html on the server-side,
  • using pushy to leverage HTML5 history.

You don't need to pass data back to the client-side in the HTTP Response header. The trick is that Pushy will trigger when started, so you just need to wait for your page to load to call pushy/start!. In other words, mount your React app first, then start the router.

Here is a bit of my code:

(ns my.router
  (:require [pushy.core :as pushy]))

;; We need to call `pushy/start!` as the last action in the boot process or it
;; might produce unexpected behavior. Pushy uses goog.history, and the goog
;; history need to be loaded before the app starts and before the document has
;; finished loading, but triggering the routing mechanism need to be done once
;; the world is set up.
;; @see https://google.github.io/closure-library/api/goog.History.html
(defn start! []
  (pushy/start! history))

In your core namespace:

(ns your.app.core
  (:require [your.app.router :as router]))

(defn ^:export boot! []
  (do-stuff-to-set-up-your-app-state)
  (mount-your-react-app)
  (router/start!))

In your index.html:

<script … src="app.js"></script>
<script type="text/javascript">
  your.app.core.boot_BANG_();
</script>
  • I would need more details to understand what you mean. How does this solve the problem of dispatching the correct panel when the url is entered directly into the browser? – zengod Mar 06 '20 at 17:06
  • You should only redirect `/panel-x` to `index.html` on the server, and then forget about the server-side. Everything next happens client-side. When you enter the URL directly into the browser, it stays there after the `index.html` page loads. Once the page is loaded, when pushy starts, bidi will handle the URL fragment and give you back the proper client-side route. – Geoffrey Gaillard Mar 06 '20 at 17:10
  • This seems to work, but the only thing is that doing back in the browser doesn't show me the previous page, but the same page. I.e., when I'm routed to /new-uri on the button click, I can't go back correctly, but when I put the /new-uri in the browser I can. How do I fix this? – zengod Mar 06 '20 at 17:26
  • You want to make sure that pushy reacts when you click "back" (using a `console.log` is enough). If pushy does not react, then there is an issue with its initialization. Beware, since `goog.History` is installing itself globally on page load, you might want to do a hard refresh to make sure the history instance get properly initialized. If pushy does react properly but your component does not update, it might come from the usage of multimethods and you might want to look at https://stackoverflow.com/questions/33299746/why-are-multi-methods-not-working-as-functions-for-reagent-re-frame – Geoffrey Gaillard Mar 06 '20 at 17:33
  • More details here: https://stackoverflow.com/questions/60712822/cannot-go-back-with-re-frame-and-pushy – zengod Mar 16 '20 at 20:31