React fullstack architecture: When adding a react front-end to a node/express application, what aspects does react's state generally handle? - node.js

I have a fully built node/express application that I want to add react to in order to practice that relationship in full stack applications. I've built apps in react before, and in node, but never together and I am confused about how react fits into the MVC architecture.
In a react-node full stack application does react state then handle all of the data I was previously passing into my ejs views?
I have been looking through tutorials on full stack applications with node and react, but they only seem to go into issues like how does react fetch data from the back end, or how to set up the configuration,
but I get that part, I just don't understand what react does in a full stack application, what part of the model-controller-view architecture of a node/express backend app does react take over? How are the responsibilities split between the backend and front end?
So for example, I'm working with a reddit-clone type app so when you click on a post title to see the post my controller queries the database for that post and then passes it to the view as {post}:
show(req, res, next){
postQueries.getPost(req.params.id, (error, post) => {
if(error || post == null){
res.redirect(404, "/");
} else {
res.render("posts/show", {post});
}
});
},
So when I add a front-end with react, would that {post} object then be something handled by react? So react would fetch that data and use it in a post component to create what is currently my view show.ejs file?

So when I add a front-end with react, would that {post} object then be something handled by react? So react would fetch that data and use it in a post component to create what is currently my view show.ejs file?
Yes. The show.ejs would be a React view or a page that contains a component to handle how to show it.
To simplify:
React -- is a virtual DOM, so it'll swap views/containers/components in and out based upon events (like clicking a button), which in turn, will: retrieve, display, manipulate and/or send data to the API. In development, it is completely separate from your back-end. All the routing will be handled by a front-end router package. In production, all of the front-end src code is compiled into a dist or build folder that contains your assets (images, fonts, css) and most importantly bundle.js file(s) that are then served by express.
Express + some database -- will act as your API where it'll CRUD data based upon the front-end request(s). If your app is a MPA (multiple page application), then a common practice is to delineate your back-end routes from your front-end routes with a /api/ prefix. In production, if express doesn't recognize the route (it's not a /api/ request), then it'll fall back into the front-end bundle.js file where it'll be handled by the front-end router.
See a working example here: https://github.com/mattcarlotta/fullstack-mern-kit (client is the frontend, everything else is the backend)
Or
See a working codesandbox (where I'm making a GET request to an API that returns json):
For your example above, your show controller will just be sending JSON (or a string message) back to the frontend (redirects will happen on the frontend via a router -- like react-router-dom):
show(req, res, next){
postQueries.getPost(req.params.id, (error, post) => {
if(error || post == null){
// res.status(404).send("Unable to locate posts.");
res.status(404).json({ err: Unable to locate posts });
} else {
res.status(200).json({ post });
}
});
},
You can even simplify the above using async/await:
const show = async (req, res, done) => {
try {
const post = await postQueries.getPost(req.params.id);
res.status(200).json({ post });
} catch(err) {
// res.status(404).send("Unable to locate posts.");
res.status(404).json({ err: Unable to locate posts });
}
};
And then the React front-end handles the response.

Related

How to connect react js front-end with node js back-end?

I'm working on a web application built with react js in the front-end and express js in the back-end, i'm also using MongoDB as a database.
I was following this tutorial in which the YouTuber is using Axios in order to connect between the react js application and the express js API.
Right now i have two questions :
is Next JS used for these kind of things ? if not, what is Next js ?
Should i use Axios like the tutorial ? or there is a better solution for this situation ?
Thank you in advance.
Next Js is basically lets you build server-side rendering and static web applications using React.
You can use following way to connect to your Nodejs backed from react using axios
axios.post(url,data, {
headers: {
'authorization': your_token,
'Accept' : 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => {
// return response;
})
.catch((error) => {
//return error;
});
Where your_token is authenticate token if you have any, url is the nodejs url you want to access and data is the body you supply to post data to your node server.
To fetch data you can use the awesome built in fetch or axios library:
fetch(/* url to your backend, eg. http://localhost:3000/mydata */
, /* notice comma */
/* other options, eg. method: โ€postโ€ */)
.then(response => res.json() /* convert server response from string to JSON */)
.then(data => /* your data array or object like */)
for details: MDN: fetch API
check your browser's console for cors issues ๐Ÿ˜Ÿ
Using create react app you are building a single page app (SPA) which is the standard, that whole app served as a JS bundle to your client browser and after that you fetch data only from server.
On the other hand Nextjs is a server side rendering which is the best of two worlds, it helps with higher page ranking on search engines, lift the heavy load from clients especially (low powered mobile devices) and more
Check this if interesting nextjs

Node.js / Express.js + Angular router - server overwriting client view with response object when using direct link

I am building a node.js app with express, I am hosting an Angular SPA in the public folder.
The app runs and the hosting works fine when I use the angular router for navigation around the website, but when I directly try to access the link, for example: http://192.168.1.4:3000/posts, the entire body of the website is just the JSON response object, without the app
this is the Node.js code handling the get request
postRouter.route('/')
.options(cors.corsWithOptions, (req, res) => {
res.sendStatus(200);
})
.get(cors.cors, (req, res, next) => {
posts.find({})
.then((post) => {
res.status(200);
res.setHeader('Content-Type', 'application/json')
res.send(post);
}, (err) => next(err))
.catch((err) => next(err));
})
this is my angular service sending out the get request
getPosts(): Observable<Post[]> {
return this.http.get(baseURL + 'posts')
.catch(error => { return this.processHttpService.handleError(error); });
}
Post Component .ts file
ngOnInit() {
this.postService.getPosts()
.subscribe(posts => { this.posts = posts, console.log(this.posts); },
errmess => this.errMess = <any>errmess);
}
Again, when i use my Angular 5 client app hosted in the public folder, built with ng build --prod, the JSON object is retrieved from the mongodb database and is displayed correctly on my website, along with the rest of the app, the header, the body, and the footer.
it might also be worth noting that the console.log on the ngOnInit() is not displayed on the browser when using the direct link.
Any advice/fix is greatly appreciated
You have a clash of routes between angular and your express application. Angular is served up on one route (I'm guessing the / route) and then it sort of "hijacks" the users navigation. It does this by not actually changing web pages, instead it just changes the URL in the navigation bar, but never actually makes a web request to get to that resource.
You've then got endpoints on a web server listening on those endpoints. This means the moment you visit the /posts page, you're not asking angular to do anything. In fact, angular isn't even loaded because that only gets loaded on the / route. Instead you're going straight to your API.
There are ways around this, to start with many people put their API fairly separately, either on a subdomain or mounted on /api (such as /api/posts). Then your angular app can be served up on the / route. There are other techniques you can use to then allow a user to go to /posts and still get your angular app loaded.
You can use a few approaches for this such as the hash location strategy, or you can serve up your angular application from any route on the application (* in express) and load the angular app which will then take over. This second approach is most comment, it usually results in hosting your api on a sub domain and then serving your angular app on the * route of the normal domain name. For example: api.myapp.com will serve only JSON responses, but any route on myapp.com will serve the angular app, such as myapp.com/posts.

How to make Express return a new html with axios post

I have an express server. I have two routes as get methods.
app.get('/main',(req, res) => {
res.sendFile(`main.html`, {root: staticPath});
});
app.get('/signin', (req, res) => {
res.sendFile('signin.html', {root: staticPath});
});
I want to build my app as a single page react application. But before I let the user see this single page, I want to show a sign in, sign up screen. So when user clicks the sign in or sign up buttons, I want to send signin.html as response from the express server.
Here is my code on the browser from a react class
SignIn(){
axios.get('signin');
}
I can console.log() from the express route and verify that the code gets executed within the 'signin' route, but the html view doesn't change on the browser even though I send back a html file. How do I make it happen?
I'm by no means an expert, but here are my two cents. Instead of setting up your front end to receive an HTML file from the server, a more efficient approach would be the following.
Build the signup and login pages on the front end.
Set up routing between these pages.
Send the login/signup details from client to server via /login or /signup routes that you set up in Express. These details would usually be in the req.body object (make sure to install the bodyparser package from NPM).
You could then use JWTs to authenticate users and maintain sessions.
If you're looking for server-side rendering with React, here is an article for your reading pleasure :) Sorry if I made no sense.

React router 4 - Link to page outside react app

I'm building a node + react app that uses passport's facebook authentication. Getting this authentication to work involves hitting an express route '/auth/facebook'. Unfortunately as soon as the react app loads up react router 4 doesn't allow links to directly hit the express server and instead searches for a react route matching 'auth/facebook'. In short how do I link to a route within my application but outside of the react app when using react router 4?
React Router is only for client side routing. Use fetch API or a similar library for that.
I'll state one way of solving your problem (using fetch and without react router).
Remove the href from the <a> tag
Add an event listener for the click event, <a onClick={makeCall}>
Then in the makeCall function, you can call the backend using the fetch API(or axios or whatever),
makeCall() {
fetch('/auth/facebook', options)
.then((res) => {
// Something
})
.catch((err) => {
// handle error
});
}

Node Express API + Front-End

I'm coding my first "solo" nodejs webapp. Its based on a previous app (that I coded by following some kind of tutorial/course) which was an Express REST API that allows you to add/remove/update/list a Todo list. I've also implemented user authentication using jwt/bcrypt. All this is stored in a MongoDB database.
Also note that all the endpoints return JSON.
I'm now trying to add a front-end to the app. The API endpoints are at /api/endpoint1, /api/endpoint2, etc., and the views are rendered on /view1, /view2, etc. I'm doing this on purpose so that I can get the responses in plain JSON from the API, or show it in a webpage rendered.
I started by using jQuery's ajax to make the calls but I realized this was not the way I wanted to do this. I removed all the js scripts on my webpage and started working directly on the server, rendering the pages with the info fetched from the api.
This is what I have now:
server.js (main file) [sample]
// RENDER 'GET TODOs'
app.get('/todos', authenticate, (req, res) => {
let auth = req.cookies['x-auth'];
request({
url: 'http://localhost:3000/api/todos',
headers: {
'x-auth': auth
}
}, function (error, response, body) {
if (error || response.statusCode !== 200) {
return res.status(response.statusCode || 500).send('Error'); // TODO
}
let bodyJSON = JSON.parse(body);
res.render('todos', {
title: 'Todo App - Todos',
todos: bodyJSON.todos
});
});
});
// API endpoint to 'GET TODOs' (JSON)
app.get('/api/todos', authenticate, (req, res) => {
Todo.find({
_creator: req.user._id
}).then((todos) => {
res.send({todos});
}, (err) => {
res.status(400).send(err);
});
});
I don't know why, but all this looks weird to me. I'm wondering if this is how I'm supposed to do this. I mean, is this a good approach/practice on making a API+front-end node app ?
Also, I'm using an auth middleware twice: in the views and in the API itself. I guess this is OK?
It would probably be better to use React/Angular but this is such a small app and I just wanted to make a really simple front-end.
Just keep things simple.
If you go with server-side HTML rendering, you don't need a REST API, just drop it. You need an API in case of an ajax frontend or mobile app.
If you needed a combined approach (server-side rendering + mobile app or server side rendering with some ajax), at the very first step you would want to isolate your database querying code into a separate module (which is actually always a good idea) and use the module from your API and from your views directly, avoiding API usage from server-side views.
This way you will eliminate excessive auth and make debugging much easier, also your code will become cleaner, thus more maintainable.
Also, React is not that complex, i would definitely give it a shot :)

Resources