I have an app and part of it is to login with twitter.
After successfully logged in, I will usually pass the user data to the template by
app.get('/', function(req, res, next) {
log("The Home page has the user info: ", req.session.user);
res.render('pages/home', {
app: 'home',
user: req.session.user || ''
});
});
And then you can render the template based on the user data.
But in React, how should I pass such data to the component after logged in?
I am thinking of putting the data in the browser directly, but I am not confident about that.
<script type="javascript">
var user = #{user}
</script>
How do you think?? Thanks.
Usually you send the props you pass to the top level component to the client in a script tag.
So, you're doing <MyApp user={user} /> or MyApp({user: user}), you would create a script tag like this:
var code = "<script>var __react_preload_data = "
+ JSON.stringify({user: user})
+ ";</script>";
And on the client side:
React.renderComponent(MyApp(__react_preload_data), document.body);
There is a library that works well with express (and any other view rendering node framework) called react-helper (https://github.com/tswayne/react-helper). It pretty much handles everything you need to do to render react components in your view and pass data to them from the server in any node framework. You just make an entry point (js file) for webpack (the lib has a cli that can generate your webpack config for you) and add a line to your controller and view and your component will render on that page. Passing data into your react components is really simple:
const component = reactHelper.renderComponent('MyComponent', {user:
req.session.user || ''})
res.render('view-to-render', {component})
There is also express middleware for react-helper (https://github.com/tswayne/express-react-helper) that allows you to add context that is available to all views, which is convenient for user session data.
app.use(function(req, res, next) {
req.reactHelperContext.user = req.session.user || '';
});
Then, all of your react components will have the user prop without having to manually add that logic to every controller action.
Related
I am new to Express and writing an application in node js. I am having problem in using the same parameters. My code is:
app.get('/signin', function (req, res) {
renderView(req, res, 'signin.jade');
});
app.get('/config', function (req, res) {
addOrUpdateGroupConfig(req.query.group_name, req.query.webhook_url);
renderView(req, res, 'config.jade');
});
app.post('/config', function (req, res) {
..
}
function renderView(req, res, view, locals) {
if (locals === undefined) {
locals = {};
}
res.render(view, locals);
}
The sign in jade redirects to app.get(/config) and i am getting webhook_url and group_name. Now I am rendering a config jade page which has form post, after submit the control comes to app.post(/config) now the problem is i want the webhook_url and group_name here to store in database. SO how to pass those values in a good way ?
If the webhook_url and group_name values can't be put into the web page for security reasons, then the usual solution would be to create a session object and store it for that specific user in their session. Then, on the POST, you could get it out of that user's session. The express-session module is available to help you create a session object for each user. This is breaking with the usual stateless design of web pages so there'd have to be a really good reason to go this way.
Otherwise, the value should probably just be inserted into the form in a hidden field (by your renderer) so that when the POST happens, the value will be sent back with the form and you'll have everything you need in the POST data. That keeps your system entirely stateless which is good for a lot of reasons (simplicity, scalability, reliability, etc...).
I use express.js, mongodb, ejs. In the navbar, there's an email icon and will display the count of new emails.
<%=newEmailCount%>
Then I need to add this newEmailCount to every route.
Emails.count({userId: userId, new: true})
my question is in express.js, how can I add a global function that can be executed by every route?
If you want to get the count for every GET requests then you can use following approach
router.get('*', function(req, res, next) {
res.locals.newEmailCount = Emails.count({userId: userId, new: true})
next();
})
You need to make sure this is always executed by placing it above all the other routes.
You can then pass res.locals.newEmailCount to your render function which renders HTML file for matched route.
This will work also for application instance level routes handling if that's what you're using.
I am building a blog like app, and posts can be created in the admin dashboard and the public user can visit a published post via the category and permalink.
I have having issues thinking about how to register the routes in my express app.
The solution I have in mind is to fetch all posts and use a for loop to register the routes on app init. The controller is pretty simple, just render the same template.
posts.forEach((post)=> {
app.get(':' + post.category + '/:' + post.slug, renderPostGenericController);
})
Will like to vet this solution and know if there is any other better way to do this.
You can register one route:
app.get('/post/:category/:slug', (req, res) {
// req.params.category
// req.params.slug
...
});
This way, in your route handler you'll have access to both parameters. Now you can fetch the correct post from the DB (or wherever) with the provided category and slug.
I currently have an app which uses Express with Jade templates.
I'm building a new version of the app using Angular with client-side HTML.
I need access to certain request parameters in order to determine user permissions in my Angular code. My problem is that I don't know how to get ahold of these parameters in my Angular controllers/services.
Below is what currently occurs in Express with the Jade structure:
routes.js:
router.get('/player/:id',
playerRoute.show
);
player.js:
var show = function(req, res) {
res.render('player', {user: req.user});
};
...and now my new version's handler:
var player = function(req, res) {
//res.sendFile(path.join(__dirname, '../v2', 'index.html'));
res.json({user: req.user});
};
The correct user JSON is sent back to my client-side with the code above. When res.json is commented out and res.sendFile uncommented the correct HTML is rendered. My dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
After all that, your question just boils down to:
MY dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
You don't. The usual case is to just render the HTML along with the assets needed to render the initial app (hide everything, show a splash screen whatever). Further data (like getting your user) is handled by API calls to your server via Angular's HTTP facilities. That means they are separate. After that API call, your app determines what to render.
Otherwise, you could just render the data in the HTML as some global variable and have Angular pick it up from there. This is messy IMO, but doesn't require a separate API call to get the data.
copied from my own answer to a similar question
To get a variable from server to client javascript try templating a json string into the html and loading it from the javascript. EJS handles quote escaping and I think Jade does too. For reference content!= safeString tells Jade to skip escaping, so does content !{safeString}.
- var user={id:1, displayName:'foo'}
#example
meta(data-userJSON=JSON.stringify(user))
script(src="//code.jquery.com/jquery-1.11.3.min.js")
script.
var user = JSON.parse(
$('#example meta').attr('data-userJSON')
)
console.log(user);
span #{user.id}
span #{user.displayName}
Here's how I ended up handling this situation. I simply created a new API endpoint which I can easily hit with an Angular service. Here's the Node setup:
routes.js:
router.get('/currentUser',
apiController.currentUser.index
);
currentUser.js:
var index = function(req, res) {
res.json({user: req.user});
};
module.exports = {
index: index
};
Still seems odd to me to make an API call to get the request parameters, but it works. Feedback appreciated.
I'm a little confused on how to add logic to the home page of my Sails.js app. Right now, its just a static page, but I would like to include data on the homepage (index.ejs). I have a MainController and I included a index: function that is pulling in the data. I can't figure out how to configure my route to allow for this.
From What you wrote I am guessing you are using Express js and ejs template.
If you are using the Express render method in your mainController to render your index.ejs you can send the data with response like:
res.render('index', { data: 'my data' }, function(err, html){
// handle callback and error
});
so here you have sent some data
then in your index.ejs file you can get data using ejs tags like:
<div><%= data %></div>
Tell me more about your mainController method if this is not useful
The static-folder is for static-content only (as the name is telling us). If you want your website to show content dynamically you need to create a controller like that:
module.exports = {
index: function(req, res){
res.view(); // sending the view in /views/{controller_name}/index.ejs
return;
}
}
Cheers!