detran
detran

Reputation: 373

reagent render multiple components

I've got two reagent components that will display on different pages of my web application. Tested individually, they both work exactly as they ought. When I try to render both of them, only one is displayed.

Here is the clojurescript:

(defn mount-components []
  (r/render [#'password-component] (.getElementById js/document "password"))
  (r/render [#'test-component] (.getElementById js/document "test")))

(defn init! []
  (mount-components))

On the back end I have this:

(defn password-page []
  (layout/base
   [:h1 "Change your password"]
   [:div#password]))

(defn home-page []
  (layout/base
   [:h1 "Hello!"]
   [:div#test]))

(defroutes app-routes
  (GET "/" [] home-page)
  (get "/password" [] password-page))

After I compile the clojurescript and look at the pages, only the password component displays. If I swap the order in the mount-components function, so that test-component is first, only test-component displays and not password-component.

How do I display both components at the same time?

Upvotes: 1

Views: 1130

Answers (1)

Tim X
Tim X

Reputation: 4235

I think the problem is possibly a type of design flaw in your implementation. In react programs, it is changes in your state atom which will trigger a re-rendering. From the provided code, it isn't clear what the 'trigger' is which will cause a re-rendering to occur. It might hlep to actually see the full page code to see how you are calling the javascript - it could simply be that init is only running with the first page load and not for every page. What could be happening is

  • You visit the first page. The mount-components function is called and finds only one of the div elements targets for your component, so you only see one component rendered.
  • You visit the second page. Now you have a page with the 2nd div element, but the problem is nothing in your local state has changed to trigger the re-rendering of components, so you don't see the second component. Basically, something needs to tell reagent/react that you need to re-render the component.

With reagent, I think it works much better if you implement the client side as a single page app (SPA). You use a reagent atom to store your app state and use the values in that atom to determine/control what/when components are rendered on the page. Calls back to the server are predominately used to just pass data back and forth rather than page html (gross simplification and overlooks things like client side rendering).

If you really want to do it the way you are, you probably need to put your render commands in different functions and then have different javascript calls in each page which will call the corresponding 'run' function which will render the component. Alternatively, you could link your components to some sort of state flag which is updated when a new page is loaded so that the mount-components function is re-run when a new page arrives.

Upvotes: 2

Related Questions