After click:
I try to test Material-UI components.
My steps:
I installed nwb globally: sudo npm install -g nwb
I created a new React application: nwb new react-app myapp
I look inside: cd myapp
I edited nwb.config.js (since Webpack creates absolute path with "/"):
module.exports = {
webpack: {
publicPath: ''
}
}
I installed requested plugin: npm i --save react-tap-event-plugin
I added font Roboto in index.html:
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
I added links to icons (because Material-UI didn't show icons by default):
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
I installed and started a server: npm start --auto-install
After starting I see an error
Invariant Violation: addComponentAsRefTo(...)
Only first button reacts on a click but it's not animation! And other buttons don't react on any clicks.
In the package.json I inserted ammendments in version of a plugin:
"dependencies": {
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-tap-event-plugin": "^2.0.1"
},
based on information from:
ERROR in ./~/react-tap-event-plugin/src/injectTapEventPlugin.js
Due to update in React, react-tap-event-plugin breaks
Change react-tap-event-plugin to ^2.0.0 in your package.json if using react version ^15.4.0.
Sorry, I don't have anymore any ideas how to fix it!
It's not working in Safari and in Chrome as well.
Thank you for any help!
All examples from official site Material-UI/Components
Related
I am building a very basic React app by including the React library script tags in my html page, and loading my components in script tags. I am not using modules or create-react-app. My components looks like this:
TIPS.JS
class Tips extends React.Component {
constructor() {
super()
}
render() {
return (
<div>
<h1>Hello World</h1>
</div>
)
}
}
I have installed the babel transpolar:
npm install babel-cli#6 babel-preset-react-app#3
And now I can transpile my JSX component to normal JS with:
npx babel --watch src --out-dir . --presets react-app/prod
This is fine, but now I want to ALSO compile Typescript TSX, but these docs are a bit unclear on how to combine these. They refer to the Microsoft Typescript React Starter, but that uses Webpack, so it's not the same setup.
Typescript setup
nom install typescript
npx tsc --init
TSCONFIG.json
{
"compilerOptions": {
"rootDir": "src",
"outDir": "build"
},
}
Now I should be able to run npm run build but I can't find the settings for package.json.
Should I use tsc watch or babel watch ? Or can I just discard babel when using typescript?
In other words, what's the most basic setup to compile TSX components to javascript without using modules and webpack?
You can compile Typescript using Babel with #babel/preset-typescript.
npm install --save-dev #babel/preset-typescript
// .babelrc
{
"presets": ["#babel/preset-typescript"]
}
So just add this preset & add tsconfig.json to your project and you will able to transpile TS.
For more info
The Problem:
I'm trying to create a website (web app) with React and Material UI, it's working just fine using npm. But when I try to make them as externals and import them through a CDN instead, I get an error with Material UI (React works fine).
My Code:
I linked CDNs in index.html like this:
<script src="https://unpkg.com/react#16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/#material-ui/core/umd/material-ui.production.min.js"></script>
<script src="app.min.js"></script>
And in app.min.js, I imported them like this:
import { Component } from 'react';
import ReactDOM from 'react-dom';
import { Button } from '#material-ui/core';
My Attempt:
In the webpack.config.js, I tried the following (again, only Material UI causes an error):
Using a string:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'#material-ui/core': 'Button'
}
gives:
Uncaught ReferenceError: Button is not defined
Using an object:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'#material-ui/core': {
Button: '#material-ui/core'
}
}
gives:
TypeError: Cannot read property 'Button' of undefined
Doing it manually, so Material UI isn't in externals:
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
Then removing minified Material UI code from app.min.js, this leaves the code incomplete and it doesn't run.
Searched through GitHub issue and SO questions without any luck, some links:
How should material-ui be externalized when bundling with webpack
Externals defined in webpack.config still getting error module not found
React CDN: Webpack externals library not resolved in code
Any idea how can I solve this?
Solution::
in webpack.config.js:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'material-ui': 'window["material-ui"]'
},
then in app.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Button } from 'material-ui';
Explanation:
If you check the cdn version of material ui js, you will find it exports its content in to material-ui namespace.
if you config webpack like:
'material-ui': 'material-ui'
webpack will compile it to:
which leads to the code looking for material and ui in global environment which does not exist. So we have to specify window["material-ui"] explicitly
Might be a little late to the party but I will add an answer which worked for me.
step 1:
add the script tag from unpkg. The difference between this and cdnjs is that unkpg have an option for umd. May or may not be an issue in your particular situation. It is for me.
url:
https://unpkg.com/#material-ui/core#4.11.0/umd/material-ui.production.min.js
script tag:
<script src="https://unpkg.com/#material-ui/core#4.11.0/umd/material-ui.production.min.js"></script>
step 1b:
add the font and font icon external resources as described in the material-ui docs:
material-ui getting started - installation guide
roboto font:
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
font icons:
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
step 2:
destructure the elements you want to use from window.MaterialUI or use the square bracket notation (but unnecessary here since this package ditched the '-' char.
const { Button } = window['MaterialUI'];
step 3:
use the element as you 'normally' would
<Button variant="contained" color="primary">
Primary
</Button>
I have just solved this issue after spending way too much time on this issue while trying to build an app using a micro-frontend architecture.
TL;DR;
The solution is to put the following in the webpack.config.js:
module.exports = {
// rest of the config clipped for brevity
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'react-router-dom': 'ReactRouterDOM',
'#material-ui/core': 'MaterialUI'
}
};
Further details:
I was building a macro-frontend composed of multiple micro-frontends. Each of the micro-frontends was developed in React, exported as a web-component, and would be independently deployed such that each micro-frontend would be available via a URL like:
http://foo.example.com/main.js
http://bar.example.com/main.js
http://baz.example.com/main.js
These would be imported into the macro-app using a <script> tag.
The macro-app was hosted on a separate domain, e.g., http://example.com.
The issue I was facing was that Material UI (and possibly React as well) was being initialized multiple times in each of the micro-apps.
To avoid that, I had to externalize all these libraries using the webpack config block above.
I had to make 2 concessions.
I did not use create-react-app and react-scripts to scaffold the macro-app because that setup would hide the webpack config. In order to expose the webpack config, I could either eject the CRA project, or use some other modules, such as react-app-rewired, etc. That felt like too much work. The downside of this was that I could not use BrowserRouter and had to accept using HashRouter for client-side routing.
I could not use SvgIcon-based icons from #material-ui/icons, because I could not find a good way of externalizing Material UI Icons. Instead, I put in a link to Material UI Icons stylesheet, and opted to use Icon from #material-ui/core/Icon to render icons. using SvgIcon-based icons was causing Material UI to be initialized in the micro-apps too, which is what I was trying to avoid. One upside of the workaround is that Icon works with Font Awesome as well, so at least all icons would be written consistently in code.
Overall, I am happy with the end results.
I'm trying to get bootstrap.css and Google fonts CDNs working in my Gatsby project.
There is no HTML file; just JavaScript files.
For bootstrap, I can npm install bootstrap and then import the min.css from that.
Trying to figure out how to get Amatic SC font from Google fonts; I have npm installed google-fonts-webpack-plugin.
I am using gatsby-node.js by adding:
const GoogleFontsPlugin = require("google-fonts-webpack-plugin")
exports.modifyWebpackConfig = ({ config, stage }) => {
config.plugin("google-fonts-webpack-plugin",new GoogleFontsPlugin(
{
fonts: [
{ family: "Amatic SC" }
]
}
),null)
};
However, I get the error below;
Invalid 'constructor' parameter. You must provide either a function or null
What am I doing wrong and how can I fix it?
Is there a way of referencing a CDN directly so rather than npm installing bootstrap, I could just reference its latest version?
You can include the font using typeface-amatic-sm from NPM, and in your JS do:
import 'typeface-amatic-sc'
Otherwise, can include scripts it in your </head> using helmet like:
<Helmet>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
</Helmet>
I am writing a npm package that depend on :
"peerDependencies": {
"react": "15.4.1",
},
"dependencies": {
"classnames": "2.2.5",
"react-onclickoutside": "5.8.3",
"styled-components": "1.1.2"
}
I have added them as peer dependencies.
I have created a webpack build, and I've generated a 'umd' module that I want to import in my application.
The probleme is that a component from the module that depend on react-onclickoutside, complain about the presence of 2 React.
This is the code that can be toggled and generate this error :
DropDown = onClickOutside(DropDown, {
handleClickOutside(instance) {
return instance.closeMenu;
},
});
This give me this error :
Error: Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: ....).(…)
If I look at my UMD module, I can see that my peer dependencies is bundled, this is probably why there is now two React in my application.
I would like to know how I can prevent webpack from bundling React react in my module
You can make use of the externals feature in webpack. Basically it will create the UMD module without bundling React, and assuming that it will be provided elsewhere
Mac OSX El capitan | angular-cli: 0.1.0 | node: 5.4.0 | os: darwin x64
I try to install a 3rd party npm module according to the angular-cli wiki: https://github.com/angular/angular-cli/wiki/3rd-party-libs but fail. I've been struggling with this for days now and would greatly appreciate any help.
Steps to get the error:
ng new lodashtest3
cd lodashtest3
npm install lodash --save
typings install lodash --ambient --save
angular-cli-build.json:
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
...
'lodash/**/*.js'
]
});
};
ng build
(lodash gets correctly added in dist/vendor)
system-config.ts:
/** Map relative paths to URLs. */
const map: any = {
'lodash': 'vendor/lodash/lodash.js'
};
/** User packages configuration. */
const packages: any = {
'lodash': {
format: 'cjs'
}
};
(all according to spec in
https://github.com/angular/angular-cli/wiki/3rd-party-libs)
Note - I've tried all config settings I can think of here, all giving the same result.
lodashtest3.component.ts:
import * as _ from 'lodash';
ng build
Could not start watchman; falling back to NodeWatcher for file system events.
Visit http://ember-cli.com/user-guide/#watchman for more info.
Build failed.
The Broccoli Plugin: [BroccoliTypeScriptCompiler] failed with:
Error: Typescript found the following errors:
/Users/danielmattsson/git/lodashtest3/tmp/broccoli_type_script_compiler-input_base_path-g2lDIaq6.tmp/0/src/app/lodashtest3.component.ts (2, 20): Cannot find module 'lodash'.
at BroccoliTypeScriptCompiler._doIncrementalBuild (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:115:19)
at BroccoliTypeScriptCompiler.build (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)
at /Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/index.js:152:21
at lib$rsvp$$internal$$tryCatch (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1036:16)
at lib$rsvp$$internal$$invokeCallback (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1048:17)
at lib$rsvp$$internal$$publish (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1019:11)
at lib$rsvp$asap$$flush (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1198:9)
at nextTickCallbackWith0Args (node.js:456:9)
at process._tickCallback (node.js:385:13)
The broccoli plugin was instantiated at:
at BroccoliTypeScriptCompiler.Plugin (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/broccoli-plugin/index.js:10:31)
at BroccoliTypeScriptCompiler.CachingWriter [as constructor] (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/index.js:21:10)
at BroccoliTypeScriptCompiler (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:26:49)
at Angular2App._getTsTree (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/angular2-app.js:280:18)
at Angular2App._buildTree (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/angular2-app.js:101:23)
at new Angular2App (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/angular2-app.js:42:23)
at module.exports (/Users/danielmattsson/git/lodashtest3/angular-cli-build.js:6:10)
at Class.module.exports.Task.extend.setupBroccoliBuilder (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/models/builder.js:55:19)
at Class.module.exports.Task.extend.init (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/models/builder.js:89:10)
at new Class (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/core-object/core-object.js:18:12)
at Class.module.exports.Task.extend.run (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/tasks/build.js:15:19)
at /Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/commands/build.js:32:24
at lib$rsvp$$internal$$tryCatch (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:1036:16)
at lib$rsvp$$internal$$invokeCallback (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:1048:17)
at /Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:331:11
at lib$rsvp$asap$$flush (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:1198:9)
EDIT: more information according to comments below
dist/index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Lodashtest3</title>
<base href="/">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Service worker support is disabled by default.
Install the worker script and uncomment to enable.
Only enable service workers in production.
<script type="text/javascript">
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/worker.js').catch(function(err) {
console.log('Error installing service worker: ', err);
});
}
</script>
-->
</head>
<body>
<lodashtest3-app>Loading...</lodashtest3-app>
<script src="vendor/es6-shim/es6-shim.js"></script>
<script src="vendor/reflect-metadata/Reflect.js"></script>
<script src="vendor/systemjs/dist/system.src.js"></script>
<script src="vendor/zone.js/dist/zone.js"></script>
<script>
System.import('system-config.js').then(function () {
System.import('main');
}).catch(console.error.bind(console));
</script>
</body>
</html>
With the stable release and current angular-cli (1.0.0-beta.15), it's simply adding the npm package plus type definitions
npm install lodash --save
npm install #types/lodash --save-dev
For early versions such as 1.0.0-beta.15, the next is necessary. It should not be required for current versions:
Add the library to the angular-cli.json to list of global scripts (add "../node_modules/lodash/lodash.js" to the list apps[0].scripts).
See https://github.com/angular/angular-cli#global-library-installation
FWIW, as of today (1.0.0-beta.26), adding the scripts entry is not necessary anymore.
Simply add the proper entries to package.json using:
npm i --save lodash
npm i --save-dev #types/lodash
Then, in your TypeScript code, use:
import * as _ from 'lodash';
The code will run just fine.
In my case, actually adding the scripts entry was causing issues.
[updated answer] After the new version of angular-cli (1.0.0-beta.15):
just add
npm install lodash --save
npm install #types/lodash --save-dev
then add the library to the angular-cli.json to list of global scripts(add "../node_modules/lodash/lodash.js" to the list apps[0].scripts).
and in your component where you want to use , try this way
declare var _:any;
#Component({
})
export class YourComponent {
ngOnInit() {
console.log(_.chunk(['a', 'b', 'c', 'd'], 2));
}
}
before : angular-cli (1.0.0-beta.15):
add this line in src/index.html
<script src="/vendor/lodash/lodash.js" type="text/javascript"></script>
and in your component where you want to use , try this way
declare var _:any;
#Component({
})
export class YourComponent {
ngOnInit() {
console.log(_.chunk(['a', 'b', 'c', 'd'], 2));
}
}
I tried straight away , it worked for me
In order to support 3rd party libraries in Angular CLI and System.js, you have to specify them manually on system.config.ts and angular-cli-build.js.
I've answered it here with example for lodash and also other dependencies.
As of 4/15/2017 with #angular/cli 1.0.0:
You need to be very specific about which versions you install otherwise the TypeScript bindings will give all sorts of failures. What I did is update my devDependencies as follows in package.json:
"#types/lodash": "ts2.0"