I'm trying to create my first component in react but I keep getting error. It results in not showing button element on the website at all. Here are my files:
ERROR in ./src/js/components/presentational/Button1.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token (3:13)
1 | import React, { Component } from "react";
2 | class Button1 extends React.Component {
> 3 | handleClick = () => {
| ^
4 | console.log("dupa");
5 | };
6 | render() {
./src/js/components/presentational/Button1.js
import React, { Component } from "react";
class Button1 extends React.Component {
handleClick = () => {
console.log("dupa");
};
render() {
return (
<button onclick={this.props.handleClick}>
Button
</button>
);
}
}
export default Button1;
./src/js/components/container/FormContainer.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Button1 from "../presentational/Button1";
class FormContainer extends Component {
render() {
return (
<Button1 />
);
}
}
export default FormContainer;
const wrapper = document.getElementById("create-article-form");
wrapper ? ReactDOM.render(<FormContainer />, wrapper) : false;
./src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" >
<title>How to set up React, Webpack, and Babel</title>
</head>
<body>
<div class="container">
<div class="row mt-5">
<div class="col-md-4 offset-md-1">
<p>Create a new article</p>
<div id="create-article-form">
<!-- form -->
</div>
</div>
</div>
</div>
</body>
</html>
EDIT
I thought I was using babel. Do I need some additional step for transpilation? Currently I'm using only
npm start
This is my package.json:
{
"name": "front-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --open --mode development",
"build": "webpack --mode production",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-latest": "^6.24.1",
"babel-preset-react": "^6.24.1",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"prop-types": "^15.6.2",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}
and this is my .babelrc
{
"presets": [
"react",
"env"
]
}
EDIT2:
Problem solved. As stated here it was because arrow functions are not included into standard right now. I had to run sudo npm install --save-dev babel-plugin-transform-class-properties and had to edit my .babelrc:
{
"presets": [
"react",
"env"
],
"plugins": [
["transform-class-properties", { "spec": true }]
]
}
You get the error because class properties (class Example { myProperty = 'foobar' }) is not a part of the language yet.
You need to add either a Babel plugin or preset for it to work. You could use the stage 2 preset.
.babelrc
{
"presets": [
"react",
"env"
"stage-2"
]
}
You can also do:
handleClick() {
// code here
}
Related
I have a Django application and trying to rewrite my JS frontend to React. I found some tutorial how to organize the structure of React app:
frontend/
static/frontend/main.js/main.js
src/
index.js
components/App.js
package.json
{
"name": "frontend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"scripts": {
"dev": "webpack --mode development ./src/index.js --output-path ./static/frontend/main.js",
"build": "webpack --mode production ./src/index.js --output-path ./static/frontend/main.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.20.12",
"#babel/preset-env": "^7.20.2",
"#babel/preset-react": "^7.18.6",
"babel-loader": "^9.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"dependencies": {
"fs-promise": "^2.0.3"
}
}
webpack.config.js
module.exports = {
devtool: false,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: { presets: ['#babel/env','#babel/preset-react'] },
}
}
]
}
};
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Django REST with React</title>
</head>
<body>
<h1>Anything</h1>
<div id="app">
<!-- React will load here -->
</div>
</body>
{% load static %}
<script src="{% static "frontend/main.js/main.js" %}"></script>
</html>
sample code in App.js
import React from 'react';
import ReactDOM from 'react-dom';
function App() {
const [value, setValue] = React.useState(0);
function increment() {
setValue(value + 1);
}
return (
<div className="app">
<h1>{value}</h1>
<button onClick={increment}>+1</button>
</div>
);
}
ReactDOM.render(
<div>
<App />
</div>,
document.getElementById("root")
);
const container = document.getElementById("app");
ReactDOM.render(<App />, container);
If I got it right, any React component imported in index.js will be compiled to js code in main.js which is included to index.html. I created a simple code in App.js just to try it and it does work, but it generates a 30k lines main.js file. Is it normal? I guess it shouldn't be like this since it consumes much more resources than my 400-lines js code, so what am I doing wrong ?part of code in main.js
So here is what my code looks like
---------index.js-----
var React =require('react');
var ReactDOM =require('react-dom');
var App=require('../components/App');
ReactDOM.render(<App />, document.getElementById('app'));
---------App.js-----
var React = require('react');
class App extends React.Component {
render() {
return(
<div>
<h1>HI wassup</h1>
</div>
);
}
}
export default App;
---------package.json-----
{
"name": "views",
"version": "1.0.0",
"description": "learning",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --mode development --hot && webpack"
},
"author": "vinayak",
"license": "ISC",
"dependencies": {
"react": "^16.4.2",
"react-dom": "^16.4.2"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-react": "^6.24.1",
"html-webpack-plugin": "^3.2.0",
"unminified-webpack-plugin": "^2.0.0",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}
---------webpackconfig-----
const HTMLWebpackPlugin=require('html-webpack-plugin');
const webpack=require('webpack');
const UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
const HTMLWebpackPluginConfig=new HTMLWebpackPlugin({
template: '../../views/index.hbs',
filename:'index.hbs'
});
module.exports={
entry:__dirname + '/app/index.js',
module:{
rules:[
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader'
}
]
},
plugins: [
new UnminifiedWebpackPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development')
}
})
],
devtool: 'source-map',
output:{
filename:'app.js',
path:__dirname + '../../public/javascripts/'
},
devServer:{
inline:false
}
};
------------------folder structure-------------
|react
|node modules
|components
|App.js
|app
|index.js
Everything works fine but when I am execting the app in browser I get the react error and gives a link which displays the following.
"Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: object."
You're mixing up require, and import / export.
Since you're running webpack, all of your React code (and anything that gets transpiled by babel via webpack) should stick to using import/export. require should only be used in places like js that's directly run by node.
In your index.js, change all the requires to imports and see if that helps.
In the file index.js, you should change your code like this:
var App = require('../components/App').default;
or use import
import App from '../components/App';
I recommend using a unified usage. You can import/export or module.exports/require.
How do you make Jest play nicely with ES7 initializers? I've searched far a wide on here and other sources, but didn't find anything conclusive.
.babelrc.js
{
"env": {
"development": {
"presets": [["es2015", { "modules": false }], "react", "react-hmre"],
"plugins": [
"transform-class-properties",
"react-hot-loader/babel"
]
},
"test": {
"presets": ["env", "react"],
"plugins": ["transform-class-properties"]
},
"production": {
"presets": [["es2015", { "modules": false }], "react"],
"plugins": ["transform-class-properties"]
}
}
}
package.json
{
"name": "demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"dependencies": {
"react": "^15.5.4",
"react-dom": "^15.5.4",
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-jest": "^20.0.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.5.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"enzyme": "^2.8.2",
"react-hot-loader": "next",
"babel-plugin-import": "^1.2.1",
"enzyme": "^2.9.1",
"enzyme-to-json": "^1.5.1"
},
"scripts": {
"test": "export NODE_ENV=test && ./node_modules/.bin/jest --no-cache"
},
"engines": {
"node": ">= 7.8.0"
},
"jest": {
"verbose": true,
"collectCoverage": true,
"coverageDirectory": "__coverage__",
"mapCoverage": true,
"setupFiles": [
"./tests/setup.js"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"transform": {
"\\.js$": "../node_modules/babel-jest"
},
"testRegex": ".*\\.test\\.js$",
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
}
Demo.jsx
import React from 'react';
import PropTypes from 'prop-types';
export class Demo extends React.Component {
static props = { name: PropTypes.string.isRequired };
constructor(props) {
super(props);
}
render() {
return (
<div className='demo'>{this.props.name}</div>
);
}
}
Demo.test.js
import React from 'react';
import { Demo } from '..';
import { render } from 'enzyme';
describe('Demo', () => {
it('renders correctly', () => {
const wrapper = render(<Demo name="foo" />);
expect(wrapper).toMatchSnapshot();
});
});
After running yarn test or export NODE_ENV=test && ../node_modules/.bin/jest --no-cache, Jest will complain that it sees an unexpected character
8 | props = {
| ^
9 | name: PropTypes.string.isRequired
From my understanding, the environment variable set when we run the tests should automatically transform the initializers to something which can be used by Jest, but this doesn't appear to be happening.
I am also using webpack 2.x, but the configuration overhead to get that to work seems daunting. Is there another way?
Update 1
I modified my Jest settings as follows:
"transform": {
"\\.js$": "./node_modules/babel-plugin-transform-class-properties"
}
This failed immediately with:
TypeError: Jest: a transform must export a process function.
Removing transform altogether yields a slightly different issue:
TypeError: Cannot read property 'props' of null
I also added the constructor to the Demo component.
I believe if you are trying to add propTypes, with ES7 initializers and using the transform-class-properties you need to do
static propTypes = {
name: PropTypes.string.isRequired
};
So it would be
import React from 'react';
import PropTypes from 'prop-types';
export class Demo extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired
};
render() {
return (
<div className='demo'>{this.props.name}</div>
);
}
}
Pretty sure you do not have to explicitly define props as it is part of the React.Component when you extends from it. That or you may need to declare constructor and then call super(props);
Jest uses babel to transpile JS code. You need to add support for ES7 features in .babelrc file.
Here are the steps:
Do npm install --save-dev babel-preset-stage-0 babel-jest
In your package.json, add babel-jest for transforming all the js files.
In your .babelrc file, add "stage-0" preset.
Here is how my package.json looks like:
...
"jest": {
"transform": {
"^.+\\.js$": "babel-jest"
}
}
...
And here is how my .babelrc file looks like:
{
"presets": [
"es2015",
"react",
"stage-0"
]
}
I'm having trouble getting decorators such as #observable and #computed to work in my project.
Here are my files.
package.json:
{
"name": "heroku-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"babel-plugin-syntax-decorators": "^6.13.0",
"mobx": "^3.1.11",
"mobx-react": "^4.2.1",
"react": "^15.5.4",
"react-dom": "^15.5.4"
},
"devDependencies": {
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-stage-1": "^6.24.1",
"react-scripts": "1.0.7"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
App.js:
import React, { Component } from 'react';
import './App.css';
import GameBoard from './components/game-board';
import { inject, observer } from 'mobx-react';
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
</div>
<GameBoard />
</div>
);
}
}
export default App;
.babelrc:
{
"presets": [
"es2015",
"react",
"stage-1"
],
"plugins": ["transform-decorators-legacy"]
}
When I add the #observer decorator like so (#observer class App extends Component {...}) before my class declaration I receive this error:
Failed to compile
./src/App.js
Syntax error: Unexpected token (7:0)
5 | import { inject, observer } from 'mobx-react';
6 |
> 7 | #observer class App extends Component {
| ^
8 | render() {
9 | return (
10 | <div className="App">
Look like you are using create-react-app and didn't make eject. In order to use decorators you should make it. Or use custom-react-scripts as alternative.
Proper way of installing mobx when you are using create-react-app is as follows;
create-react-app ExampleApp
npm run eject
npm install --saveDev babel-plugin-transform-decorators-legacy
Update your .babelrc file as it is right now (with transform-decorators-legacy)
npm install --save mobx mobx-react
That should do the trick.
In my case I don't use 'stage-1' but I have the following plugins
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
]
and these dependencies in package.json
"babel": "^6.23.0",
"babel-loader": "^7.1.2",
And as you try different configs make sure the public/packs folder get cleared out. I run into some trouble with cached files.
i create test react project. Add modules and my packege.json look like:
{
"name": "untitled",
"version": "0.1.0",
"private": true,
"devDependencies": {
"babel-preset-node5": "^12.0.1",
"react-scripts": "0.9.5"
},
"dependencies": {
"babel-preset-stage-0": "^6.22.0",
"history": "^4.6.1",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-native": "^0.42.3",
"react-router": "^4.0.0",
"react-router-config": "^1.0.0-beta.1",
"react-router-dom": "^4.0.0",
"react-router-native": "^4.0.0",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.2"
},
"scripts": {
"start": "react-scripts start",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"build": "babel input.js -o compiled.js"
}
}
and webpack.config.js
var config = {
entry: './index.js',
output: {
path:'/',
filename: 'index.js',
},
devServer: {
inline: true,
port: 8080
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', "node5", "stage-1", 'react', "stage-0"]
}
}
]
}
};
module.exports = config;
in my component i import component Link from react-router-native and after this adding react show error 'Uncaught SyntaxError: Unexpected token export' but if i delete this string project work well. it's not the only component in the module, i can add any components like Promt, Route or Router. Why it's not work with Link?
This is code where error reproduced
import React from 'react';
import { Route, Router } from 'react-router';
import { Promt } from 'react-router';
import { Link } from 'react-router-native';
import logo from '../../logo.svg';
import './App.css';
class App extends React.Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;
You need to update the regular expression for the test value in your web pack config to be test: /(\.js|\.jsx)$/
Right now you are telling webpack to only run .js files through babel loader, but you aren't telling it to also run .jsx files through babel loader.