I cannot seem to get React to work - reactjs

I have been trying to setup webpack, babel, and npm to work with react. I followed the guide on codeacademy - https://www.codecademy.com/articles/react-setup-v. On their last step, they say to create an App.js. Now App.js is a js file, therefore no JSX synthax can be written. This is how my App.js looks:
var React = require('react');
var Component = React.createClass({
render: function (){
return(
<p>Hello World</p>
)
}
});
module.exports = Component;
Now, I know why it throws me an error of unexpected token at line 5 of the code. JS does not recognize the paragraph tag. I tried converting the file to jsx, but that way I cannot import it in my index.js file. I have been trying to setup react for days, and it is very frustrating because I just want to start coding with React very soon.

Related

React.js + OpenCV.js ReferenceError: cv is not defined

I can't run opencv.js and react.js together because (I think) opencv.js is too big (7.8mb) for yarn to compile (I get max callstack error). Given that, I also can't load opencv.js in the index.html because it loads too slowly for React to pick it up, giving me cv is not defined.
Creating an onLoad="myfunc()" function gets me furthest, as I can set a var loaded to be true and wrap an if statement around the ReactDOMrender. But it doesn't ever pick up when the var changes to true and never renders.
I've tried the following:
Importing the opencv.js script right into my index.js where I'm testing this out. I get a Max callstack error. I'm guessing this is because opencv.js is around 8mb and the compiler doesn't like it?
I've tried to add opencv.js in the public/index.html file. I load it using async and add /*global cv*/ to the top of my index.js file. I get the error cv is not defined.
import React from 'react';
/*global cv*/
var mytest = function() {
var test = cv.Mat();
console.log(test + ' if you see something before this, opencv loaded');
}
mytest();
function App() {
return (
<div>hello world</div>
)}
export default App;
and in the of the index.html:
<script async src="opencv.js" type="text/javascript"></script>
This fails and says cv is not defined. I've also tried this with an onLoad="whenOpenCvLoads()" using this function to set a var to be true, and wrapping (what I believe to be) the first called function in react like this:
if(openCvIsReady === true){
ReactDOM.render(<App />, document.getElementById('root'));
console.log(openCvIsReady + ' in react');
}
This evaluates to false and never runs when the variable eventually becomes true.

Render reactdom on dynamic ids (React JS)

we have a CMS build on PHP, which uses custom modules.
Each module is rendered as HTML document and can be included(hooked) on every single page and has its own, dynamic aund unique ID in the html.
Now I would like to create a JavaScript Template System for this modules where the React appliaction could be rendered on each module.
For example I have created my react bundle. And I also have my single page with module which generates the modules with module html where react should be rendered. And I would like my react bundle to render on this id instead of:
ReactDOM.render(<App />, document.getElementById('root'));
The ID mod-123416-name is automatically created, so that I want with some code for example RenderReactOn("mod-123516-name") on the client side to render one react bundle on each module with this id.
So I can render the same react code on n different modules on the client side:
RenderReactOn("mod-123516-name");
RenderReactOn("mod-252141-name");
RenderReactOn("mod-453467-name");
Is this possible with react, or what are the best practices in such cases. Maybe I should take Knockout.js instead of react?
Thanks in advice
Tony
This is not a problem at all, I'd do it this way:
Bundle your Components (React Apps) in a single File:
import React from 'react';
import { render } from 'ReactDOM'
import ReactAppOne from 'ReactAppOne'
import ReactAppTwo from 'ReactAppTwo'
const Apps = {
ReactAppOne,
ReactAppTwo,
}
function renderAppIn(elementId, appId) {
const APP = Apps[appId]
if (!APP) return;
render(<APP />, document.getElementById(id))
}
// simply assign that function to the window
window.renderAppIn = renderAppIn;
In your rendered html:
<div id="some-app-123"></div>
<div id="some-app-xyz"></div>
<script src="/js/bundle.js"></script>
<!-- Render your Render Stamements -->
<script>
renderAppIn('some-app-123', 'ReactAppOne')
renderAppIn('some-app-123', 'ReactAppTwo')
// render the same app in another div
renderAppIn('some-other-div', 'ReactAppTwo')
</script>

Cannot resolve module

Complete react newb here. I am having a really stupid issue trying to use components. When i have the components in the index.js (entry file) it works fine with import. however when i try to reference it from another component it ONLY tries to resolve the path from the parent component.
Root
- Example/Example.js
- Test/Test.js
/* In Test.js */
var Test= React.createClass({
render() {
return <div>
"Hello"
</div>
}
});
export default Test;
/* In Example.js */
import Test from './Test/Test';
var Example = React.createClass({
render() {
return <div>
<Test />
</div>
}
});
export default Example;
Now i get error:
Cannot resolve module './Test/Test' in G:\app\root\example <--- here it only looks in the root.
I think its a webpack issue? I have tried the docs and suggestions for adding resolve.root but that didnt seem to help. Being a newb I am not sure if the issue is react or webpack or where to fix it.
Your path to Test is incorrect. It should be ../Test/Test

WebPack with React Uncaught Reference Error

I'm very loosely following the example here up until the point where it starts running the dev server.
I have a test React component (in scripts/test.jsx):
/** #jsx React.DOM */
var React = require('react');
var Test = React.createClass({
render: function(){
return <h1>HI!</h1>
}
});
module.exports = Test;
I have a webpack.config where I'm using the jsx loader against the source directory (It's basically the same as the one in the example except I'm adding the library properties).
I run webpack and it generates the bundle file like I expect, however, when I try to use the component in an html file (after including the bundle.js script reference) I get the following in console: "Uncaught ReferenceError: Test is not defined".
The HTML contains the following:
<div id="hi">
</div>
<script type="text/jsx">
/** #jsx React.DOM */
React.renderComponent(
<Test />,
document.getElementById('hi')
);
</script>
Am I doing something incorrect to use a component that is defined in CommonJS style against an html page that isn't technically using a module loader (I'm trying to treat this test as if it's someone who is trying to load the component without any type of structured module loader)?
The output of the webpack is available here
EDIT 2: The full example code is available as a github repo
Yeah, you'd be better off following the example and requiring Test from a .jsx file rather than inlining it in the HTML.
Otherwise, Test needs to be exported as a global, so you'd need to follow similar conventions to the browserify --standalone flag, which looks to be something like this:
output: {
library: "Test",
libraryTarget: "umd"
}
http://webpack.github.io/docs/webpack-for-browserify-users.html#standalone
Edit: After looking at your GH repo, you have:
<script src="bundle.js" type="text/js"></script>
instead of
<script src="bundle.js" type="text/javascript"></script>
so it wasn't loading bundle at all. Further, you can't have 2 separate copies of react, the way you have it currently you're requiring React from within webpack, and then you're also loading it on the page. You should either export a function which takes the React object, or use the global to be able to use it outside of the bundle.
For example this would work:
/** #jsx React.DOM */
module.exports = function(React) {
var Test = React.createClass({
render: function(){
return <h1>HI!!</h1>
}
});
return Test;
};
and then:
/** #jsx React.DOM */
React.renderComponent(
Test(React)(),
document.getElementById('hi')
);
or this
/** #jsx React.DOM */
var Test = React.createClass({
render: function(){
return <h1>HI!!</h1>
}
});
module.exports = Test;
and then:
/** #jsx React.DOM */
React.renderComponent(
<Test />,
document.getElementById('hi')
);
Though I can't imagine most folks consuming a React package are going to be loading it with a script tag, and you generally don't want globals, so it's probably best to just use the CommonJS style require and let people figure out shimming or whatever.

Organizing a React JS project - building single JS file

I just got started using React. I went through the CommentBox tutorial without any issues. But the framework does not give much/any guidance to organizing your JS files or compiling a single minified JS file for a SPA. I already know the framework is flexible and does not enforce a standard and I'm sure these questions are probably dead obvious for someone who develops in the Javascript ecosystem.
I would imagine the consensus is to use Browserify and in the docs there's a link to a git starter project:
https://github.com/petehunt/react-browserify-template
This is a good start, but still it only compiles a single JS file "index.js". I read through some of the browserify handbook and I thought I simply had to 'require' my other files (and those files need to export themselves).
So I modified index.js to look like this:
/** #jsx React.DOM */
var React = require('react');
var pkg = require('./package.json');
var commentBox = require('./comment-box.js');
comment-box.js is basically a hello world test:
/** #jsx React.DOM */
var React = require('react');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
React.renderComponent(
<CommentBox />,
document.getElementById('content')
);
module.exports = CommentBox;
If I run the react-browserify-template's start target it seems to generate browser-bundle.js fine:
npm start
But if I try the build target
npm build
...nothing happens. I changed the output of npm to verbose and I get the following:
npm info it worked if it ends with ok
npm verb cli [ 'node', '/usr/local/bin/npm', 'build' ]
npm info using npm#1.4.21
npm info using node#v0.10.24
npm verb exit [ 0, true ]
npm info ok
According to package.json it's supposed to generate a file "browser-bundle.min.js" but instead I get no output. I'm hoping someone can clear this up.
I figured out what the problem was. As I stated originally, it is probably obvious for someone who's been developing in the JS ecosystem :)
The package.json in the react-browserify-template has three scripts in the "scripts" section with the keys "start", "build", and "test".
As I said previously, start worked fine by running:
npm start
I wrongly assumbed that I could run the build script similarly:
npm build (this will never work and there will be no errors/output)
It turns out I needed to run the build script using:
npm run-script build
One extra line in the documentation might have saved me hours of trouble :D I'm now using this approach as it seems quite a bit simpler. Also, it sets NODE_ENV to production and uses envify which apparently is important: https://github.com/facebook/react/issues/1772
One other thing, some of the official examples such as todomvc-flux use the lowercase 'react' in the require function:
var React = require('react');
so I suppose that's the recommended syntax (?)
Working solution using Felix's gist. Note: This is not 100% equivalent to the react-browserify-template which uses envify and the production flag to get rid of some React debugging (mainly "Download the React DevTools for a better development experience: http://fb.me/react-devtools" which is printed to the console on startup).
Perhaps a mod can give Felix credit for the solution?
App.js
/**
* #jsx React.DOM
*/
"use strict";
var React = require('React');
var CommentBox = require('./components/CommentBox.js');
React.renderComponent(
<CommentBox />,
document.getElementById('content')
);
components/CommentBox.js
/** #jsx React.DOM */
var React = require('React');
var CommentList = require('./CommentList.js');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList />
</div>
);
}
});
module.exports = CommentBox;
components/CommentList.js
/** #jsx React.DOM */
var React = require('React');
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
Hello, world! I am a CommentList.
</div>
);
}
});
module.exports = CommentList;

Resources