Share user object between several react_components

154 Views Asked by At

What is the best way to share a user object between multiple react_component other than hanging it off of window?

For example -

<%= react_component("HelloWorld1", { user: @user }) %>
<%= react_component("HelloWorld2", { user: @user }) %>
1

There are 1 best solutions below

0
On

If you're using React and HTML.ERB for the frontend

I think the way you currently have it is the best way to do it if you want to combine HTML.ERB and React.

Just as you can't pass down a prop to two components at once when dealing with pure React, I don't think you can do it in this case too.

If you're only using React for the frontend

Note: I'm not sure how the following would affect SEO.

You could use the Rails app as an API, and display your React app using a single HTML tag in static_pages#root (or similar). And then use react-router-dom for routing and changing pages on the frontend.

That way you don't have to keep rendering html.erb templates that you may pass instance variables to. You'd be fetching data and modifying it using API requests.


Extra details

If you choose to do the second method (using react-router-dom), then the files might look something similar to the following:

routes.rb

Rails.application.routes.draw do
  namespace :api, default: { format: :json } do
    resources :users, only: [:index, :show, :create, :destroy]
    # ...
  end
  root to: 'static_pages#root'
end

app/controllers/static_pages_controller.rb

class StaticPagesController < ApplicationController
  def root
  end
end

app/views/static_pages/root.html.erb

<main>
  <%= react_component("App") %>
</main>

app/javascript/components/App.jsx

import React, { useState, useEffect } from 'react';
import {Switch, Route} from 'react-router-dom';
import { Auth } from './auth/Auth.jsx';
import { HelloWorld1 } from './hello/world1/HelloWorld1.jsx';
import { HelloWorld2 } from './hello/world1/HelloWorld2.jsx';

const App = () => {
  const [user, setUser] = useState(null);

  if (!user) {
   return (
     <Auth setUser={setUser} />
   );
  }

  return (
     <Switch>
      <Route 
       exact
       path="/hello/world1" 
       render={(props) => <HelloWorld1 user={user} {...props} />}
      />

      <Route 
       exact
       path="/hello/world2" 
       render={(props) => <HelloWorld2 user={user} {...props} />}
      />

      {/* ... */}
    </Switch>
};

export default App;