Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

107
Views
React rendering JSON instead of component on page reload

I've deployed my MERN app on Heroku and everything was fine until I realized an issue every time I refresh the page or try to access a route from the address bar. While navigation through React Router links is fine, trying to go directly to a route from URL address bar or refreshing the page is causing the app to break and sending server responses directly to the browser instead of rendering the component - to clarify: if a given route was supposed to make a GET request and display some data, the actual JSON is displayed on-screen.

As far as I've checked, this is happening only on components that make a GET request.

server.js

// INITIATE APP
const app = express();

// MIDDLEWARE
app.use(express.json());
app.use(cookieParser());
app.use(cors());
app.use(passport.initialize());

const isProduction = process.env.NODE_ENV === "production";

// Priority serve any static files
isProduction &&
  app.use(express.static(path.resolve(__dirname, "../client/build")));

// CONNECT TO DATABASE
// db config
const dbConnection = isProduction
  ? process.env.MONGO_URI_PROD
  : process.env.MONGO_URI_DEV;

mongoose.connect(dbConnection, () => {
  console.log("Successfully connected to database");
});

// ROUTES
const authRouter = require("./routes/auth");
const detailsRouter = require("./routes/details");
const diaryRouter = require("./routes/diary");
const resultsRouter = require("./routes/results");
const settingsRouter = require("./routes/settings");

app.use("/auth", authRouter);
app.use("/details", detailsRouter);
app.use("/diary", diaryRouter);
app.use("/results", resultsRouter);
app.use("/settings", settingsRouter);

// All remaining requests return the React app, so it can handle routing
isProduction &&
  app.get("*", function (request, response) {
    response.sendFile(path.resolve(__dirname, "../client/build", "index.html"));
  });

// DEFINE PORTS
const port = process.env.PORT || 5000;

// START SERVER
app.listen(port, () => {
  console.log(`Server started on port ${port}`);
});

By the end of the code above, right before Define ports, there is this statement that I included to fix a similar issue happening on other routes too. I thought this was going to prevent this error in any situation, but it seems that this isn't the case. You can try the app here (you can delete the account on /settings after testing).

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

I'd like to thank S. Elliott Johnson for the solution I'll post below to anyone running into the same issue in the future:

This sounds like intended behavior. Your server routes and your React Router routes SHOULD NOT conflict.

React Router isn't actually "routing" anywhere from a HTTP sense -- it's just rendering different JavaScript/HTML and storing its "location" in the URL.

When running a React app, the React app is typically only served from the root of your website (or some other "root", like mydomain.com/app). When you make a HTTP GET request to that route, the backend server sends all of the JavaScript, HTML, and CSS necessary to bootstrap your React app. Clicking around using React Router simply causes your React code to run on the client.

When you actually reload the page, your browser, as you know, makes a GET request back to the server for that route, so you just get whatever your server sends. Let's use a few examples where you have a React app that's served from my domain.com.

Example 1:

  • User makes a browser GET request to mydomain.com. They receive the React app back

  • User navigates to /auth/login - no HTTP requests, React simply running code

  • User navigates to /me to view their account -- again, same

  • User reloads the page using the browser - a HTTP GET request is sent to the backend, and they'll receive whatever the backend sends back -- whether that's JSON or something else

You really have two options here:

  1. Redirect all HTTP requests to root, meaning /, /something and /anything will serve /. Then host your API on another subdomain, like api.mydomain.com

  2. Choose a route to serve your API from, like mydomain.com/api. Forward all requests from any route EXCEPT /api and it's subroutes to the root.

What I ended up doing was option 2:

Renamed my API routes prepending /api to all of them on server.js. Then I renamed all API calls on React accordingly. That code excerpt

isProduction &&
  app.get("*", function (request, response) {
    response.sendFile(path.resolve(__dirname, "../client/build", "index.html"));
  });

on server.js took care of the GET requests executed on page refresh, making sure that Node always serves index.html to supply those requests.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!