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.
Related
Many articles and tutorials teach how to share components in monorepo projects.
But they show something in an unproductive way.
Share each component (package1, package2) separately in workspace. What I intend to do is export a complete package using atomic design, coming from a ui package only.
But when trying to do this this error is generated
I'm importing this way
import { Button } from 'ui/atoms'
package.json
{
"name": "ui",
"version": "0.0.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"license": "MIT",
"scripts": {
"dev": "tsc --watch --outDIr dist",
"build": "tsc --outDir dist",
"lint": "eslint *.ts*"
},
"devDependencies": {
"#types/react": "^18.0.17",
"#types/react-dom": "^18.0.6",
"eslint": "^7.32.0",
"eslint-config-custom": "workspace:*",
"react": "^18.2.0",
"tsconfig": "workspace:*",
"typescript": "^4.5.2"
}
}
Using import from "ui" it works, that is, we would have to keep creating files like Button.tsx and importing them in the ui index and using them in the project, but it is inefficient, imagine thousands of components (atoms, molecules).
import * as React from "react";
export * from "./Button";
I think I'll have to share other config files, so I'll be willing to change the post and put them.
App.tsx - Importing ui
import React from 'react';
import './App.css';
import { Button } from 'ui/atoms'
function App() {
return (
<div className="App">
<Button/>
</div>
);
}
export default App;
package.json
{
"name": "main_",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"#testing-library/user-event": "^13.5.0",
"#types/jest": "^27.5.2",
"#types/node": "^16.18.3",
"#types/react": "^18.0.25",
"#types/react-dom": "^18.0.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"typescript": "^4.9.3",
"web-vitals": "^2.1.4",
"tsconfig":"workspace:*",
"ui":"workspace:*"
},
"scripts": {
"dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
link to the repository
micro-frontend
Ui library is being used in "apps/main_/src/App.tsx
After a while without messing with monorepo, I came back these days and found the solution for it.
Let's go to the problem I reported, and considered unfeasible.
Many monorepo projects using Turbo using component sharing as follows.
//index.tsx
export { Avatar, AvatarGroup } from "./components/avatar";
export type { AvatarProps, AvatarGroupProps } from "./components/avatar";
export { Badge, UpgradeTeamsBadge } from "./components/badge";
export type { BadgeProps } from "./components/badge";
export { Breadcrumb, BreadcrumbContainer, BreadcrumbItem } from "./components/breadcrumb";
export { Button, LinkIconButton } from "./components/button";
export type { ButtonBaseProps, ButtonProps } from "./components/button";
export { ButtonGroup } from "./components/buttonGroup";
export {
Checkbox,
EmailField,
EmailInput,
FieldsetLegend,
DropdownMenuLabel,
Steps,
WizardForm,
SettingsToggle,
Stepper,
Switch,
} from "./components/form";
Realize that you have to keep importing all your components in the index, so that you can use them in other projects.
Correction
To resolve, just add the other files to eslint
"scripts": {
"lint": "eslint *.ts* atoms/**"
},
With that there will be no need to import all the components in the index, in fact, you don't even need to have it
I'm trying to use jest.spyOn() for my tests instead of jest.mock since the return value of a mock can't be type-checked. When I use it though, I get the following error:
TypeError: Cannot set property useGame of #<Object> which has only a getter
> 3 | const STATE_SPY = jest.spyOn(hooks, "useGame");
| ^
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:852:26)
at Object.<anonymous> (src/components/game/game.test.tsx:4:24)
My files are structured like:
src/
- game.test.tsx
- game.tsx
- hooks/
- index.tsx
- use-game.tsx
And here is how my code is laid out (I removed a lot of extraneous code for this question
to make it easier to read).
/hooks/index.tsx:
export { default as useGame } from "./use-game";
use-game.tsx:
export default function useGame(initScore: number) {
const [score, setScore] = useState(initScore);
return {
score,
setScore,
}
}
game.test.tsx:
import * as hooks from "./hooks";
const STATE_SPY = jest.spyOn(hooks, "useGame");
game.tsx:
import React from "react";
import { useGame } from "./hooks";
const STARTING_SCORE = 50;
export default function Game(): JSX.Element {
const {score} = useGame(STARTING_SCORE);
return (
<div>
{score}
</div>
)
}
I think the issue is how useGame is exported as a module. But I haven't figured out a way to export/import it "correctly". Of course, there could be another issue that I'm unaware of.
App was created with create-react-app.
My package.json in case that helps.
{
"name": "greatest-game-of-all-time",
"version": "0.1.0",
"private": true,
"dependencies": {
"#material-ui/core": "^4.11.0",
"#material-ui/icons": "^4.9.1",
"#types/jest": "^24.9.1",
"#types/node": "^12.12.53",
"#types/react": "^16.9.43",
"#types/react-dom": "^16.9.8",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-hook-form": "^6.1.2",
"react-scripts": "^3.4.1",
"typescript": "^3.9.7"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#testing-library/dom": "^7.21.5",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/react-hooks": "^3.4.1",
"#testing-library/user-event": "^7.2.1",
"prettier": "2.0.5",
"react-test-renderer": "^16.13.1"
}
}
I looked through your package.json and noticed that the package #testing-library/react-hooks had been added earlier. I propose to use it in order to write new tests for hooks.
You can read the documentation to get started https://github.com/testing-library/react-hooks-testing-library
It seems you use babel to transpile your code. As I know that if you import with wild card (namespace) like that. It will create a object contains your named exports as getter like
var obj = { get namedExport: () => ... }
so in this case, I suggest to either mock entire module:
jest.mock('./hooks', () => ({ useGame: yourMock }))
or switch to tsc by using ts-jest to fix your issue (since tsc won't use getter to export that named export)
I got jest working on my react app and I'm trying to run tests, but I'm getting an error. When I run the test with "scripts": {"test": "react-scripts test --env=jsdom"} almost every test works. I had to change my tester to "test":"jest" to get the last test working, but now the test are crashing on compile because the < in the multiple shallow(<ReactPage />) is throwing an error.
From my understanding of the code, my test should be fine. Should be some setting for jest that I have to make in the project.json file to fix this error?
Test
import {shallow, mount, configure} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import ReactDOM from 'react-dom';
import jest from 'jest';
import ReactPage from './App';
configure({ adapter: new Adapter() });
it('renders ReactPage without crashing', () => {
const div = document.createElement('div');
ReactDOM.render( <ReactPage /> , div);
ReactDOM.unmountComponentAtNode(div);
});
package.json
{
"name": "client-charts",
"version": "0.1.0",
"private": true,
"dependencies": {
"async": "^2.6.1",
"moment": "^2.22.2",
"react": "^16.4.2",
"react-dom": "^16.4.1",
"react-scripts": "1.1.4",
"recharts": "^1.1.0",
"react-table": "^6.8.6",
"react-snapshot": "^1.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && react-snapshot",
"test": "jest",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000",
"devDependencies": {
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"jest": "^20.0.4"
}
}
You are missing a step to process the JSX. If you are using babel, add a react preset to your .babelrc file. More info can be found here: https://jestjs.io/docs/en/getting-started#additional-configuration
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
}
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.