reactjsruby-on-railsheroku

React Component in Rails App Appears on Localhost but not Heroku Production


I have a Rails 7 app (esbuild, NO webpacker) with multiple React components, most of which work perfectly on localhost and in my Heroku production environment.

Weirdly enough, this one component is just...not appearing on Heroku.

import React, { useEffect, useState } from 'react';
import QuizResultsCategoryChart from './QuizResultsCategoryChart';

const QuizResultsDashboard = ({ userId }) => {
  console.log("QuizResultsDashboard rendered");

  const [categoriesData, setCategoriesData] = useState([]);
  const [measurementsData, setMeasurementsData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(`/api/v1/construct_measurements`)
      .then(response => {
        if (!response.ok) {
          console.error('API response not ok:', response.status, response.statusText);
          throw new Error(`Network response was not ok: ${response.status} ${response.statusText}`);
        }
        return response.json();
      })
      .then(data => {
        console.log('API response:', JSON.stringify(data, null, 2));
        setCategoriesData(data.categories);
        setMeasurementsData(data.measurements);
        setLoading(false);
      })
      .catch(error => {
        console.error('Fetch error:', error);
        setError(error.message);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div className="quiz-results-dashboard">
      {categoriesData.map(category => (
        <div key={category} className="fc-content-box mb-8">
          <QuizResultsCategoryChart
            category={category}
            measurements={measurementsData.filter(m => m.category === category)}
          />
        </div>
      ))}
    </div>
  );
};

export default QuizResultsDashboard;

This displays on localhost, but on Heroku not even the initial console.log statement shows.

I've reduced it to just:

import React from 'react';

const QuizResultsDashboard = ({ userId }) => {
  console.log("QuizResultsDashboard rendered", { userId });
  return <div>Quiz Results Dashboard for user {userId}</div>;
};

export default QuizResultsDashboard;

And still nothing appeared.

Just to narrow it down:

Here's how it's being summoned in application.js:

// For Quiz Results Dashboard
import QuizResultsDashboard from './components/QuizResultsDashboard';
document.addEventListener('DOMContentLoaded', () => {
  const quizResultsDashboardContainer = document.getElementById('quizResultsDashboard');
  if (quizResultsDashboardContainer) {
    const userId = quizResultsDashboardContainer.getAttribute('data-user-id');
    const root = createRoot(quizResultsDashboardContainer);
    root.render(<QuizResultsDashboard userId={userId} />);
  }
});

And here's how it's summoned in the view:

    <div class="fc-container">
        <div id="quizResultsDashboard" data-user-id="<%= current_login.user.id %>" ></div>
    </div>

My heroku logs -t shows nothing useful:

2024-07-23T03:12:42.859672+00:00 app[web.1]: I, [2024-07-23T03:12:42.859618 #34]  INFO -- : [d424bebf-fc11-4b76-9d05-49b167025acc] Started GET "/users/progress" for 70.181.107.14 at 2024-07-23 03:12:42 +0000
2024-07-23T03:12:42.860792+00:00 app[web.1]: I, [2024-07-23T03:12:42.860753 #34]  INFO -- : [d424bebf-fc11-4b76-9d05-49b167025acc] Processing by UsersController#progress as HTML
2024-07-23T03:12:43.349754+00:00 heroku[router]: at=info method=GET path="/users/progress" host=frayachat.ai request_id=d424bebf-fc11-4b76-9d05-49b167025acc fwd="70.181.107.14" dyno=web.1 connect=0ms service=490ms status=200 bytes=15033 protocol=https
2024-07-23T03:12:43.347886+00:00 app[web.1]: I, [2024-07-23T03:12:43.347818 #34]  INFO -- : [d424bebf-fc11-4b76-9d05-49b167025acc]   Rendered layout layouts/application.html.erb (Duration: 484.4ms | Allocations: 77633)
2024-07-23T03:12:43.348030+00:00 app[web.1]: I, [2024-07-23T03:12:43.348010 #34]  INFO -- : [d424bebf-fc11-4b76-9d05-49b167025acc] Completed 200 OK in 487ms (Views: 467.8ms | ActiveRecord: 17.7ms | Allocations: 78691)
2024-07-23T03:12:44.283798+00:00 heroku[router]: at=info method=GET path="/favicon-32x32.png" host=frayachat.ai request_id=fb19e919-ede8-4f54-868c-a2fe63b2251c fwd="70.181.107.14" dyno=web.1 connect=0ms service=1ms status=304 bytes=131 protocol=https
2024-07-23T03:12:44.446818+00:00 heroku[router]: at=info method=GET path="/site.webmanifest" host=frayachat.ai request_id=00aeda22-86ce-4866-a118-ebf9d94c4ee2 fwd="70.181.107.14" dyno=web.1 connect=0ms service=1ms status=304 bytes=131 protocol=https

And yes, I asked several of the AIs and they don't know either.

Can anyone suggest something that may give me a lead as to why this is just...not appearing on Heroku? I'm legitimately stumped.

EDIT

The mysteries continue. I updated my application.js with some console logs:

// For Quiz Results Dashboard
import QuizResultsDashboard from './components/QuizResultsDashboard';
console.log("THE APPLICATION JS IS HAPPENING.")
document.addEventListener('DOMContentLoaded', () => {
  console.log("IT IS HITTING INSIDE THE DOCUMENT LISTENER.")
  const quizResultsDashboardContainer = document.getElementById('quizResultsDashboard');
  console.log(quizResultsDashboardContainer);
  if (quizResultsDashboardContainer) {
    const userId = quizResultsDashboardContainer.getAttribute('data-user-id');
    const root = createRoot(quizResultsDashboardContainer);
    root.render(<QuizResultsDashboard userId={userId} />);
  }
});



// For MessageBoard
import MessageBoard from './components/MessageBoard';
document.addEventListener('DOMContentLoaded', () => {
  const messageBoardContainer = document.getElementById('messageBoard');
  console.log("WE'RE IN THE MESSAGE BOARD")
  if (messageBoardContainer) {
    const userId = messageBoardContainer.getAttribute('data-user-id');
    const root = createRoot(messageBoardContainer); 
    root.render(<MessageBoard userId={userId} />);
  }
});

NONE of them showed up. (Localhost yes, worked as expected. Heroku? Nothing.) Not even the one that just showed the application.js was loaded.

Weirder still, the one in the MessageBoard component didn't show up, yet that component works perfectly on Heroku.

So I'm thinking that may be a dead end.

I also found that in the sources tab in "frayachat.ai > assets > application-20520584fb71b3636c0801c48020cebd161c1969bb546da69142b50f9eee3e3b.js" I did a search for a working component and it showed up, but I searched for "QuizResultsDashboard" and it doesn't appear in it at all.

I have since run assets:clobber and assets:precompile in both environments and updated my package.json:

{
  "name": "app",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-free": "^6.5.2",
    "@hotwired/stimulus": "^3.2.2",
    "@hotwired/turbo-rails": "^8.0.4",
    "@rails/actioncable": "^7.1.3-2",
    "@tailwindcss/forms": "^0.5.7",
    "autoprefixer": "^10.4.19",
    "axios": "^1.6.8",
    "chart.js": "^4.4.3",
    "esbuild": "^0.20.2",
    "esbuild-plugin-jsx": "^1.0.1",
    "lodash": "^4.17.21",
    "postcss": "^8.4.38",
    "react": "^18.2.0",
    "react-actioncable-provider": "^2.0.0",
    "react-chartjs-2": "^5.2.0",
    "react-datepicker": "^7.3.0",
    "react-dom": "^18.3.1",
    "react-infinite-scroll-component": "^6.1.0",
    "react-intersection-observer": "^9.10.2",
    "react-markdown": "^9.0.1",
    "react-window": "^1.8.10",
    "tailwindcss": "^3.4.3"
  },
  "scripts": {
    "build": "esbuild app/javascript/*.* app/javascript/**/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets --loader:.js=jsx --loader:.ttf=file --loader:.woff2=file --external:@rails/actioncable",
    "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify"
  },
  "devDependencies": {
    "@babel/preset-react": "^7.24.1",
    "esbuild-plugin-copy": "^2.1.1"
  }
}

Still no luck and none of the application.js console.log statements in production.


Solution

  • So after a LOT of digging, it appeared that none of my JS assets were getting recompiled and transmitted to Heroku at all.

    I ended up having to remove my public assets from my gitignore (sending them straight to Heroku without the asset pipeline), which fixed the issue. Then when I readded them to gitignore it had somehow gotten past the block, so it worked just fine.