hurricanenate

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

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

hurricanenate

Yeah, that approach definitely works. I was hoping for a more integrated solution that doesn’t require those kinds of explicit pass-throughs.

Where Next?

Popular in Questions Top

WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 43487 311
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43757 214
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31265 143
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement