I have created a react app that's a server side rendered, the problem am facing is setting up API calls. basically i want to get data from the database but i couldn't figure out how to do it properly.
As you may know in the static MERN App / REST API the server sends data according to the requested routes through the data property, then we get it in the client using res.data but in the server side rendered app i can't do that because the server always sends HTML tag of the page that we request to the client through res.data property which makes sense, but what are the correct approach of setting up routes in a way that we can get and post data to the database in server rendered app
Any help would really be appreciated, Thanks in advance
server/server.js
import React from "react";
import express from "express";
import compression from "compression";
import { Provider } from "react-redux";
import ReactDOMServer from "react-dom/server";
import { StaticRouter } from "react-router";
import store from "../client/store/store";
import App from "../client/App";
import mongoose from "mongoose";
import path from "path";
import fs from "fs";
import cors from "cors";
import User from "./model/users";
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors());
app.use(compression());
app.use(express.json());
app.use(express.static("./build/public"));
mongoose
.connect(
process.env.MONGODB_URI,
{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
}
)
.then(() => {
console.log("Connected to the Database...");
})
.catch(err => console.log("ERROR: " + err));
app.get("*", (req, res) => {
const content = ReactDOMServer.renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={{}}>
<App />
</StaticRouter>
</Provider>
);
const indexFile = path.resolve("./build/public/index.html");
fs.readFile(indexFile, "utf8", (err, data) => {
if (err) {
console.log(err);
return res.status(500).send("Oops, Something went wrong!");
}
return res.send(
data.replace(
'<div id="root"></div>',
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>My App</title>
</head>
<body>
<div id="root">${content}</div>
</body>
</html>`
)
);
});
});
// app.get("/api/getData", (req, res) => {
// User.find({}, (err, users) => {
// if (err) throw err;
// res.json({ newUser: users });
// });
// });
app.listen(PORT, () => {
console.log("server is listening to port:", PORT);
});
client/client.js
import "./assets/scss/styles.scss";
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
import store from "./store/store";
function importAll(r) {
let images = {};
r.keys().map(item => {
images[item.replace("./", "")] = r(item);
});
return images;
}
importAll(require.context("./assets/images", false, /\.(png|jpe?g|svg)$/));
ReactDOM.hydrate(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.querySelector("#root")
);
client/App.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { Route, Switch } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Themes from "./pages/themes";
import Contact from "./pages/Contact";
import ErrorBoundary from "./pages/ErrorBoundary";
class App extends Component {
render() {
return (
<ErrorBoundary>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<Route exact path="/themes" component={Themes} />
<Route exact path="/contact" component={Contact} />
</Switch>
</ErrorBoundary>
);
}
}
export default connect()(App);
client/pages/Home.js
import React, { Component } from "react";
import { connect } from "react-redux";
import axios from "axios";
class Home extends Component {
componentDidMount() {
axios
.get("api/getData")
.then(res => {
if (res) {
console.log(res.data);
}
})
.catch(err => console.log(err));
}
render() {
return (
<div><h1>Welcome Home</h1></div>
);
}
}
export default connect()(Home);