hurricanenate
How to integrate Phoenix with a React SPA
My company is taking its first steps in integrating an existing React SPA into a brand-new Phoenix app. We’ve set up auth using phoenix.gen.auth, and are looking at the first case where we need Phoenix-generated data in our UI layer: adding a logout link to our header.
This is how the link is generated in _user_menu.html.heex:
<li><%= link "Log out", to: Routes.user_session_path(@conn, :delete), method: :delete %></li>
What’s the best way to recreate this in our React app?
The first approach I came up with was to add a template that puts any data we might need into a <script></script> tag and attaches it to the window object so that our React components could grab it. This is how I implemented it:
root.html.heex:
<head>
...
<%= render "_script_data.html", assigns %>
...
</head>
_script_data.html.heex:
<script type="text/javascript">
window.dashboardAppData = {
currentUser: {
<%= if @current_user do %>
email: '<%= @current_user.email %>',
<% end %>
},
csrfToken: document.querySelector("meta[name='csrf-token']").getAttribute("content"),
routes: {
userSessionDelete: '<%= Routes.user_session_path(@conn, :delete) %>',
...
}
}
</script>
My React component, HeaderToolbar.js:
function HeaderToolbar() {
const appData = window?.dashboardAppData;
return (
{appData && (
<a
href={appData.routes.userSessionDelete}
data-to={appData.routes.userSessionDelete}
data-method="delete"
data-csrf={appData.csrfToken}
>
Log Out
</a>
}
)
}
This approach seems workable, but far from ideal: I don’t love the step of creating a giant object of data and making decisions each time about naming conventions. I also lose the utility of the <%= link ... %> tag, as I’m forced to recreate what a Phoenix link looks like, mirroring the necessary data attributes first by rendering it normally in a template and then recreating it in my React component.
Does anyone have any suggestions for better ways to approach this integration? Whatever choices we make at this point will determine the pattern for how we do quite a bit of other work and I’d like to find the best option possible.
Most Liked
bpaulino0
Probably very late on the topic, but back in 2022, I wrote a blogpost on how to integrate the entire React pipeline within Phoenix so you can have a decent developer experience, but also a reasonable deployment pipeline that does not compromise on your current Elixir/Phoenix build steps.
I think the most challenging part is to make sure that you have a up2date build step for your SPA app and at the same time you don’t change your Phoenix setup too much. And you only need NodeJS during build-time.
hurricanenate
Yeah, that approach definitely works. I was hoping for a more integrated solution that doesn’t require those kinds of explicit pass-throughs.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









