In my recent applications I've been using Flux (with flummox - http://acdlite.github.io/flummox) on server per request to make isomorphic rendering. Generally it looked as follows:
app.use(createFluxPerRequest);
app.get('/some-route', (req, res) => {
api.getData(data => {
req.flux.getActions('items').receiveItems(data);
next();
});
});
app.use((req, res) => {
ReactRouter.run(routes, req.url, Handler => {
res.render('base', {
snapshot: new Buffer(req.flux.serialize(), 'utf-8').toString('base64'),
appString: React.renderToString(
React.createElement(Handler, { flux: req.flux })
)
});
});
});
As you see I've been receiving data through api services however some React components make requests on client on their own.
They doing this by calling e.g. flux.getActions('items').getSomeDataAsync action in container components (in componentDidMount lifecycle method).
My question - is it possible (from your experience) to have some method inside container component that will be called on server to call async actions inside it?
Check out react-nexus
Even though it still remains a work in progress, I think that would "answer" your question
We want to keep fetching data from within the components, but have this data also possibly rendered server side - that's where "isomorphic" will really mean something to react
Too bad this isomorphic word got hyped before actually solving this issue
Yes, I've been using an isomorphic API that can be called from the server and the client in a big react-based isomorphic SPA.
This library that makes it so you can build your APIs in an isomorphic fashion, and re-use it in the client and server without bloating or breaking the bundle. This is what we're currently using in a big single-page application.
It's called Isomorphine, and you can find it here: https://github.com/d-oliveros/isomorphine.
Disclaimer: I'm the author of this library.
Related
I’m always coding backend api’s and I don’t really get how express does its bidding with my code. I know what the request and response objects offer, I just don’t understand how they come to be.
This simplified code for instance:
exports.getBlurts = function() {
return function(req, res) {
// build query…
qry.exec(function(err, results) {
res.json(results);
}
});
}
}
Then I’d call in one of my routes:
app.get('/getblurts/, middleware.requireUser, routes.api.blurtapi.getBlurts());
I get that the function is called upon the route request. It’s very abstract to me though and I don’t understand the when, where, or how as it pertains to the req\res params being injected.
For instance. I use a CMS that modifies the request object by adding a user property, which is then available globally on all requests made whether ajax or otherwise, making it easy at all times to determine if a user is logged in.
Are the req and res objects just pre-cooked by express but allow freedom for them to be modified to your needs? When are they actually 'built'
At its heart express is actually using node's default http-module and passing the express-application as a callback to the http.createServer-function. The request and response objects are populated at that point, i.e. from node itself for every incoming connection. See the nodeJS documentation for more details regarding node's http-module and what req/res are.
You might want to check out express' source code which shows how the express application is passed as a callback to http.createServer.
https://github.com/expressjs/express/blob/master/lib/request.js and https://github.com/expressjs/express/blob/master/lib/response.js show how node's request/response are extended by express specific functions.
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.
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 :)
While there used to be very good documentation for using sockets, thanks to Irl Nathon's Sails Cast series. Things have changed in v0.11, with the sails team wrapping and burying the socket.io routines.
The sails site e.g. SailsSocket is maddeningly concise, saying what to do, but not how or where to do it, or if I need to npm or bower something. This has been particularly frustrating trying to use the sails.config.sockets talked about on the sails site. Which I cannot even find in my v0.11 directories.
First, I would like to know how and where to create my own response to a io.socket.get or .post or whatever. Right now when I do a get with something like:
`io.socket.request({
method: 'get',
url: '/sites/2',
params: {},
headers: {}
},function serverResponded(body, JWR){console.log("Body: ", JSON.stringify(body,null, 4)); console.log(' JWR: ', JWR.body)});'
I get back:
undefined
VM1149:7 "Not implemented in core yet"
VM1149:7 JWR: Not implemented in core yet
I can see the sites being called in the sails console, but nothing comes across.
I believe it is because I have defined my own routes and have my own find: function in my site controller and I manually need to push something into the server side socket. But I am confused as to how I am to call a whole page with HTTP and just the tables with socket.io in the same controller routine.
Where do I write my own low level socket.io routines that can be called from a web page?
Do I still do it in the app.js file?
Sails Cast showed it being done there, but again things have changed.
Sails "virtual requests" (what they call these socket.io-based HTTP-ish request) are generally used to retrieve or post JSON data to the server. Additionally, if a client-side script makes a virtual request, the server may add or remove the requesting socket to/from rooms.
Note that using a "virtual method" will ultimately run the same controller action, but will set req.isSocket = true.
This example is a view that renders a view for HTML-wanting requests but returns JSON data for socket-based requests:
...
// 'get /sites/:id': 'SomeController.showSite' (should be put in your `routes.js`)
showSite: function(req, res) {
// load something from the database
Site.findOne(req.param('id')).exec(function(err, site) {
// handler errors (same for HTTP or sockets)
if (err) return res.serverError();
if (!site) return res.notFound();
if (req.isSocket) return res.json(site); // render JSON response for our `site` object
else return res.view('sites/show', {site: site}); // render an HTML view
});
}
As for low-level socket.io, sails provides the global variable io (from sails.io.js), which is an instance of SailsSocket. It allows you to make HTTP-ish "virtual requests". More info here (although it seems you have already read all there is to read about SailsSocket :). You can access the underlying socket.io client with io.socket._raw.
// do this in the browser.
// sails.io.js should be included in layout.ejs by default.
io.socket.get('/site/2', console.log); // "virtual request"
// neat little trick ^^^^^^^^^^^ for testing :)
var rawIO = io.socket._raw;
rawIO.emit('some:event', "using native socket.io");
Hope this helps!
I need to make an API request to an external API using an API Key. I know how to make this API request in React by writing a onSubmit function. But since I have an API key that I want to keep a secret I am going to write a simple Node app to house env variables.
Besides messing around in node this is my first production experience with Node and I am wondering if my thought process is correct and if not, the better way to do this.
Most of this question will be pseudo code since I haven't started with the Node portion yet.
The idea is that from within the React component it would call the Node app who in turn would call the external API.
React -> Node -> External API
So the React component would be something like so:
handleSubmit: function() {
var data = this.refs.testData.getDomNode().value;
$.ajax({
url: '/my-node-endpoint',
dataType: 'json',
type: 'POST',
data: { test: data },
success: function(data) {
// Whatever success call I want to make
}.bind(this)
})
}
And then in my Node app it would like something like this:
app.post('/my-node-endpoint', function(req, res) {
// Store the values we are posting as JSON
// Start the post request
// On End tell the React component everything is ok
// Prosper
});
As always, thanks for any help that is offered.
Your thought process looks right to me.
If the API you are calling is from a different domain, you will have to build a wrapper on your node server like you did here. Unless the external API supports cross-origin requests with no domain restrictions (such as MapBox web services), you will have to do this.
Several improvements to your code:
As far as I know, you can use React.findDOMNode(this.refs.testData).value instead of this.refs.testData.getDomNode().value. getDomNode() is deprecated in v0.13.
For all the AJAX calls, you can use the Store concept in Flux. The store keeps the states of the data, including updating data through AJAX request. In your React UI code, you just need to call the methods of the store, which makes your UI code clean. I usually create a store class myself without using Flux.