Syntax Error rendering ReactJS view - node.js

engine as an alternative to EJS in my node.js app. Anyway I used this example from here: https://github.com/reactjs/express-react-views
var React = require('react');
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
module.exports = HelloMessage;
However I'm getting this error:[SyntaxError: D:\Data\ytko\elbp\views\index.jsx:5
return ;
^
Unexpected token <];
Considering I copied this verbatim I'm slightly confused as to whats going on.
Thanks

Related

Setting/Accessing Nunjucks global variables within a NodeJS/KeystoneJS project

I've spent all of this morning searching for how to do this, and have come up stumped.
The project I'm working on is built on KeystoneJS/NodeJS. It's using Nunjucks which I've only got a few days basic experience of.
My issue is that after loading the config vars that sets the URI's/Ports of the services, I then want to set these up as Nunjucks variables, so within the html views, I can use those as the src locations.
I can't share all the code here, as I'm working on a government (UK) project but here's enough I hope.
Keystone.js
// Require keystone
var keystone = require('keystone');
var cons = require('consolidate');
var nunjucks = require('nunjucks');
var env = new nunjucks.Environment(null);
env.addGlobal('provision_uri', 3);
This loads initially, after routing it calls:
Login.js
var keystone = require('keystone');
var nunjucks = require('nunjucks');
exports = module.exports = function (req, res) {
var view = new keystone.View(req, res);
var locals = res.locals;
// locals.section is used to set the currently selected
// item in the header navigation.
locals.section = 'home';
var env = new nunjucks.Environment(null);
var provision_uri = env.getGlobal('provision_uri',3);
console.log(`Uri ${provision_uri}`); **<-- ERRORS HERE**
// Render the view
view.render('login', {
title: 'User Login',
description: 'Login to your Account',
provision_uri: provision_uri
});
};
Login.html
<br>
<form action="{{provision_uri}}/session" method="post" name="user">
<div class="container">
When I then start the project, the landing page loads, click on the login page and within console I get:
GET /provision/ 304 74.147 ms
Error thrown for request: /login
Error: global not found: provision_uri
I've checked this Question however it doesn't answer what I need but I looked up the environment.addGlobal given as an answer. That did seem to be what I wanted, but still it wouldn't work. I found this question which provided hope.
Any ideas would be great, I do have a work-around but would like to learn how to use these.
Thanks,
Colin
You don't need to create new instance of nunjucks environment on each render call. The new scope (environment) has empty global space.
var nunjucks = require('nunjucks');
var env = new nunjucks.Environment(null);
env.addGlobal('provision_uri', 3);
...
exports = module.exports = function (req, res) {
...
var provision_uri = env.getGlobal('provision_uri',3);
console.log(provision_uri);
view.render('login', {
title: 'User Login',
description: 'Login to your Account',
// provision_uri: provision_uri // it's not necessary
});
}

Cannot render my react app server side

I am trying to render a basic react component via node js .
Unfortunately i got some errors. I think this is related to es6.
The problem is i already wrote a lot of code in es6 and now i want to render it in node js. I can't rewrite my entire app, so how to import my components and make them compatible witch node js.
What is what i've tried since now :
const filePath = path.resolve(__dirname, 'index.html')
fs.readFile(filePath, 'utf8', (err, htmlData)=> {
if(err){
return res.status(404).end()
}
const app = renderToString(<ReactApp />)
const RenderedApp = htmlData.replace('{{SSR}}',app)
res.send(RenderedApp)
})
I got this error SyntaxError: Unexpected token <
This is because ReactApp is a react component
i don't know how to import it on my node.
Any solutions ?
thanks

rendering react on server

I've been trying to figure out how to render react on the server (node/express) and finally found a simple enough tutorial to understand what's going on. But now, after setting everything up, I'm getting an error in the React.render method:
here's my component file:
var React = require('react');
var box = React.createClass({
render: function() {
return (
<div style='padding: 10px'>
this.props.text
</div>
);
}
});
React.render(<box text='testing server side'/>, document.body);
module.exports = box;
I get an error when I run npm start:
document is not defined
how do I get around this? do I need or not need the render method?
to give more context, this box component is being required by another component:
var React = require('react');
var Box = require('../react-jsx/box.js'); //this is the box component
var Component = React.createClass({
render: function() {
return (
<html>
<head>
<title>
React Server Rendering
</title>
</head>
<body>
<Box text='testing'/>
<script src="public/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Component;
and this is all being used in index.js
require('node-jsx').install();
var React = require('react');
var Component = require('../custom-modules/test-react-server-module.js');
var express = require('express');
var router = express.Router();
router.get('/react', function(req, res, next) {
var markup = React.renderToString(Component());
res.send(markup);
});
module.exports = router;
and if I remove the render method I get this error in the browser:
Cannot read property '__reactAutoBindMap' of undefined
I saw some people saying that may be due to the jsx transformer being old, but I think I have the latest version
I'm out of ideas
First of all, I'd recommend update your React version. The current version exposes two different Top-Level API's: React, which is generally used to create components and ReactDOM, which exposes DOM-specific methods to be used at the top level of your app.
There is to things to point out here:
You are trying to run an code that is supposed to be executed only at the browser. There is no document in NodeJS. I'd suggest using webpack to pack this component files and serve them on browser.
For an isomorphic React application, you need to have a client.js file that calls the render function for the same component you are trying to render inside index.js. Got it?
Understand the ReactDOM.render, as the documentation states:
Render a ReactElement into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).
If the ReactElement was previously rendered into container, this will
perform an update on it and only mutate the DOM as necessary to
reflect the latest React component.
Keep in mind, again, that ReactDOM.render should be only used a few times and generally at the top level of your app, just one time.
Having said this, your box.js should look like:
var React = require('react');
var box = React.createClass({
render: function() {
return (
<div style='padding: 10px'>
this.props.text
</div>
);
}
});
module.exports = box;
For this to properly work, you will need to create a main component main-component-file.js:
var React = require('react');
var Box = require('../react-jsx/box.js'); //this is the box component
var Component = React.createClass({
render: function() {
return (
<html>
<head>
<title>
React Server Rendering
</title>
</head>
<body>
<Box text='testing'/>
<script src="public/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Component;
Inside your bundle.js you need to make sure that this is being called so the main component tries to re-render:
var React = require('react');
var ReactDOM = require('react-dom');
var Component = require('main-component-file.js');
ReactDOM.render(<Component/>, document.body);
At last but not least: index.js, the server file. Change React.renderToString to ReactDOMServer.renderToString, create a React Element from your main component and use it:
var element = React.createElement(Component)
router.get('/react', function(req, res, next) {
var markup = ReactDOMServer.renderToString(element);
res.send(markup);
});
Don't forget to include the npm package react-dom/server at your index.js.
References used in the article:
React.createElement
ReactDOM.render() docs
ReactDOMServer docs
You should delete this
React.render(<box text='testing server side'/>, document.body);
There is no need for it. What you are essentially telling React to do is render it right then and there.
document.body doesn't exist yet because you are rendering it server-side and you also don't need it because you render the component in the renderToString function upon request in the router. (Also I think #PeterLyons is correct so take a look at his answer too).
Also if you are strictly using React for views only, you might want to take a look at express-react-views. They have a good tutorial of how to use React with Express and you essentially can use it for server-side rendering only. I don't think it's as ideal as using react-router depending on what you're building but it illustrates how React is handling the server-side rendering and works with Express.
You need to use the react-dom/server package's renderToString function in the server environment. This will return the HTML as a string which you can send in your express response.

Backbone Collection only fetched after executing alert

Hey I am new to backbone and Handlebars and something strange is happening with my code that I cannot figure out. Basically my node app queries mongo for some data which is then used by backbone and handlebars to relay the data to the user. When I try to relay the data to the user by using the fetch method, I get an error from handlebars stating that I cannot call on the compile method because I passed undefined. The strange thing is that when I was debugging the code it seemed like the collection was never being created i.e no data being returned from the backend. But when I tried to alert the collection the data does get returned and displayed which is really confusing? Anyway below are a few snippets of my code, would love to know why this is happening, thanks.
Init.js - used to initialize the backbone router
$(function(){
new appRouter();
Backbone.history.start({pushState: true});
});
photoClient.js Used to define and manage model, collection & views
var photo = Backbone.Model.extend({
idAtrribute: "id",
});
var photoCollection = Backbone.Collection.extend({
model: photo,
url: "/api/gallery"
});
var photoView = Backbone.View.extend({
tagName: "li",
className: "photo",
render: function(){
var template = $("#illustrationTemplate").html();
var compiled = Handlebars.compile(template);
var html = compiled(this.model.attributes);
this.$el.html(html);
return this;
}
});
var photoCollectionView = Backbone.View.extend({
initialize: function(){
this.listenTo(this.collection, "reset", this.render);
},
tagName: "ul",
className: "photos",
render: function(){
this.$el.html("");
this.collection.each(function(photo){
var photoV = new photoView({model: photo});
this.$el.append(photoV.render().el);
}, this);
return this;
}
});
var appRouter = Backbone.Router.extend({
routes: {
"gallery": "illustration"
},
illustration: function() {
var collection = new photoCollection();
collection.fetch({reset: true});
//IF I ADD THIS ALERT THE COLLECTION IS NOW DEFINED?
alert(collection);
console.log(collection);
var view = new photoCollectionView({collection: collection});
$(".app").html(view.render().el);
}
});
Illustration.jade
extends ../layout
block content
div.app
script(id = "illustrationTemplate", type = "text/x-handlebars")
{{image.created_at}}
I'd guess that the problem is right here:
$(".app").html(view.render().el);
As soon as you do that, everything that used to be inside <div class="app"> is gone. That includes your <script id="illustrationTemplate"> that you're using to store your template. Once your router's illustration method is called, $("#illustrationTemplate").html() will give you undefined and that view will no longer work.
You should store your templates inside <head> or at the very least outside of anything that your application will be writing to.

KOA POST parsing error

I'm trying to get the POST data using koa-body-parser but I get the following error :
SyntaxError: Unexpected token e
at Object.parse (native)
This error refer to
/co-body/node_modules/raw-body/index.js
I think that the library co-body is trying to use "parse" but in my node version this function is restricted.
I'm using node 0.11.13
This is a part of the app.js
var path=require('path');
var koa = require('koa');
var app = koa();
app.use(require('koa-body-parser')());
//enrutamiento
app.use(require('./configs/routes')(app));
This is the function that recibe the call:
function *(){
/*
var str = 'email=lopezchr%40gmail.com&password=123123';
console.log(JSON.parse(str));
*/
var self = this;
var attributes= this.request.body
var userModel = this.models.user;
userModel.create(this.request.body).exec(function(){
self.body={success:true,description:"user Created"}
});
}
Aditionally, when I try to do this:
var str = 'email=lopezchr%40gmail.com&password=123123';
console.log(JSON.parse(str));
I optain the same error..
update
In other post, I realized that string is not a JSON.. sooo... that is the problem...
I'm trying to do this:
$.post('/auth',$(form).serialize(),function(data){
console.log(data);
});
And I want to recibe the form data with koa-body-parce...What should I do?
For some reazon, the jquery function $.post was sending the message with type json.. so that caused the error.. now the message type is plain/text and works.. thanks

Resources