How do I use Glimmer components inside an Ember app? - javascript

The Glimmer website states:
Just drop your Glimmer components into an Ember app. You won’t need to change a thing.
I’ve been following the official Ember quick start tutorial. I replaced the contents of the generated people-list.js component with this:
import Component from '#glimmer/component';
export default class PeopleList extends Component {
}
and I get an error in the browser console stating that #glimmer/component is undefined. After I run yarn add #glimmer/component to add the dependency, I get a new error from Broccoli.
Additionally, whenever I use '#' before a variable in the people-list.hbs template, the template fails to compile. How do I get the Glimmer component to work in my Ember app?

To use glimmer in an ember app today (May 1st, 2019),
yarn add --dev #glimmer/component#beta
then
import Component from '#glimmer/component';
import { tracked } from '#glimmer/tracking';
export default class MyComponent extends Component {
#tracked number = 0;
increment() {
this.number++;
}
}
to see this in action, take a look at a fresh Octane App: https://github.com/ember-cli/ember-octane-blueprint

Currently you can't use it for existing ember app. but you can try it brand new app. By installing ember new my-glimmer-app -b https://github.com/glimmerjs/glimmer-blueprint.git
If you go with yarn global add ember-cli/ember-cli this way then you need to uninstall existing ember-cli (npm uninstall -g ember-cli)

Related

How to use i18next as a peer dependency for my component library?

I am building a React component library which contains some translations, but I want these translations to be provided by the user of my package.
The reason for this is that these translations should be customizable, and I don't want to include every possible language in this package.
So what I'd like to achieve is to use useTranslations inside my component library like this:
import React from 'react';
import { useTranslation } from 'react-i18next';
const MyComponent = () => {
const { t } = useTranslation();
return <div>{t('helloWorld')}</div>;
};
And somehow the 'helloWorld' translations should be configurable by the user of the library.
Is there any way to achieve this?
Apparently this was caused by yarn link using two versions of react-i18next.
To solve this I've configured my app to use the react-i18next version of my package:
cd my-package/node_modules/react-i18next
yarn link
cd my-app
yarn link react-i18next
Now my package uses the i18next instance configured in my app.

How to import a component from a different drive in react?

I have a project in drive C and I need a component in some other project in some other drive D. How do I proceed?
I have a website already made without ReactJS but now I need React as it will make my work easier so I'm integrating the components this way.
Can we import components in a non-react app like this?
below is my written code
'use strict';
import App from '../../../../'; //Area of issue
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
if (this.state.liked) {
return 'You liked this.';
}
return e(
// <App />
'button',
{ onClick: () => this.setState({ liked: true }) },
'Like'
);
}
}
const domContainer = document.querySelector('#map');
ReactDOM.render(e(LikeButton), domContainer);
Yes, you can import your components from one project to another irrespective of your new project location. It's just that your project might require a little restructuring and then has to be transpiled into a ES5 package, bundled and imported into other projects like a npm package.
you can also publish it to the npm repository online and install it as a dependency in the project you want. You just need to take care of the imports and exports really well.
So, here is the basic idea..
use babel and webpack to transpile your react project and bundle into a npm package.
eg.
babel Path_of_your_c_drive_project --out-dir output_folder_path
--copy-files
Copy that npm package from the output folder and paste it in the node_modules of the new project, and then add it is as a dependency in package.json of your new project.
Import the components in the js files wherever you require in the new project, just the same way you import other packages and use them.
You might face a lot of "not found errors" if you don't give the paths correctly at all the imports and exports in the above steps.
Sadly, that is not possible.
Just store the components on the same drive, shouldn't be that much of a hassle.
Create a react project. Implement all the react components inside that with your required customizations. Then instead of directly rendering, export a function to render those components to the element reference you pass. Then build it and include the built js file in your project. Follow the links to get a better idea:
react-micro-frontends
is-it-possible-to-export-react-component-as-function-in-non-react-project
using-react-components-in-non-react-websites
add-react-to-a-website

Webpack - Alias folder for use within installed package

I have some reusable React components published to NPM, that I am installing and using within my React application. Is it possible for me to set an alias in my React app, that can be used within these NPM components? For example, I want to allow the use of a folder common, which is within my React App, within the React components. So if I do this in my React components, it should work
import someVal from 'common';
I am bundling these React components with Webpack, and sending down the transpiled, bundled version for use within the React application. I tried setting the alias the regular way within the React app webpack config (by setting resolve.alias), but it does not work. Can this be done? Or am I approaching this incorrectly? Any suggestions would be great, thanks!
Edit: So the React components from NPM are within my node_modules folder, and it is already bundled up via it's own Webpack config. I then run these components through my React application Webpack config as well (I'm whitelisting the folder), in the hopes that the new common alias will be added there. But no luck. I keep getting a
someVal is undefined error.
My common file has the following: Ignore the logic for now (I'm only posting a part of the code)
import _myClass from '../components/MyClass';
const myClass = _myClass; // Other things are done to it
export default myClass;
In my React components Webpack bundle file (after I fixed the default import statement)
/* harmony import */ var common__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! common */ "./src/common/index.js");
...
return common__WEBPACK_IMPORTED_MODULE_25__["default"].myFunction({
...
});
This still seems to be looking for common within the React components package, and not within the React app package that I am trying to use this in.

React Hooks Error: Hooks can only be called inside the body of a function component

I am getting this error when using the useState hook. I have this in it's basic form, looking at the react docs for a reference, but am still getting this error. I'm ready for the face palm moment...
export function Header() {
const [count, setCount] = useState(0)
return <span>header</span>
}
Updated: 2018-Dec
New version of react-hot-loader is out now, link. Hooks is now working out of the box. Thank to the author, theKashey.
Check out this boilerplate https://github.com/ReeganExE/react-hooks-boilerplate
React Hooks
React Hot Loader
Webpack, Babel, ESLint Airbnb
Previous Answer:
First, make sure you installed react#next and react-dom#next.
Then check for you are using react-hot-loader or not.
In my case, disable hot loader & HMR could get it work.
See https://github.com/gaearon/react-hot-loader/issues/1088.
Quoted:
Yes. RHL is 100% not compatible with hooks. There is just a few
reasons behind it:
SFC are being converted to Class components. There is reason - to be
able to forceUpdate on HMR, as long there is no "update" method on
SFC. I am looking for other way of forcing the update (like this. So
RHL is killing SFC.
"hotReplacementRender". RHL is trying to do React's job, and render
the old and the new app, to merge them. So, obviously, that's broken
now.
I am going to draft a PR, to mitigate both problems. It will work, but
not today.
There is a more proper fix, which would work - cold API
You may disable RHL for any custom type.
import { cold } from 'react-hot-loader';
cold(MyComponent);
Search for "useState/useEffect" inside component source code, and "cold" it.
Updated:
As per updated from react-hot-loader maintainer, you could try react-hot-loader#next and set the config as bellow:
import { setConfig } from 'react-hot-loader';
setConfig({
// set this flag to support SFC if patch is not landed
pureSFC: true
});
Thank to #loganfromlogan for the update.
My problem was forgetting to update react-dom module. See issue.
Had the same issue. My problem was related to React Router. I had accidentally used
<Route render={ComponentUsingHooks} />
instead of
<Route component={ComponentUsingHooks} />
I was able to solve this by importing React's primitive hooks in the component file, then passing them into my custom hooks. For some reason, the error only occurs when I import the React hook (like useState) in my custom hook file.
I'm importing useState in my component file:
import React, {useState} from 'react'; // import useState
import {useCustomHook} from '../hooks/custom-hook'; // import custom hook
const initialState = {items: []};
export default function MyComponent(props) {
const [state, actions] = useCustomHook(initialState, {useState});
...
}
Then in my hook file:
// do not import useState here
export function useCustomHook(initialValue, {useState}) {
const [state, setState] = useState(initialValue || {items: []});
const actions = {
add: (item) => setState(currentState => {
const newItems = currentState.items.concat([item]);
return {
...currentState,
items: newItems,
};
}),
};
return [state, actions];
}
This method has improved the testability of my hooks because I don't need to mock React's library to provide the primitive hooks. Instead, we can pass in a mock useState hook right into the custom hook's function. I think this improves code quality, as your custom hooks now have no coupling with the React library, allowing for more natural functional programming and testing.
I experienced this error while using Parcel's Hot Module Replacement, and fixed by updating react-dom to it's alpha version:
yarn add react-dom#16.7.0-alpha.0
See this issue.
I had a problem in a monorepo, where a package docz used react#16.6.3 and the final output bundle had two react versions.
Issue on Github
Fixed it by removing the package 😅
Just to elaborate on #rista404's answer, including duplicate versions of react (and perhaps react-dom) will yield the same error depending on where you are using your hooks. Here are two examples...
An external dependency includes another version of react in its dependencies, likely by mistake as react should usually be a peer dependency. If npm doesn't automatically dedupe this version with your local version, you may see this error. This is what #rista404 was referring to.
You npm link a package that includes react in its devDependencies or dependencies. Now, for modules in this package, you may see errors if they pull a different version of react from the their local node_modules directory rather than the parent project's.
The latter can be fixed when bundling with webpack by using resolve.alias like so...
resolve: {
alias: {
'react': path.resolve(__dirname, 'node_modules/react'),
'react-dom': path.resolve(__dirname, 'node_modules/react-dom')
}
}
This will ensure react is always pulled from the parent project's node_modules directory.
Another solution if you are running into this when using npm link:
You can npm link react in your library as explained here:
https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
or set react in your library as peerDependency and then use npm link --only=production
The problem for me was indeed react-hot-loader.
You can disable react-hot-loader for a single component instead of the entire app using the cold method like this:
import { cold } from 'react-hot-loader'
export const YourComponent = cold(() => {
// ... hook code
return (
// ...
)
})
OR
export default cold(YourComponent)
My issue was the following:
I was doing:
ReactDOM.render(Example(), app);
Whereas I should have been doing:
ReactDOM.render(<Example />, app);
For those who come across this issue when using MobX and wrapping a component with an observer, make sure you use mobx-react-lite instead of mobx-react.
MAY 29 UPDATE
From mobx-react 6.0.0 onward, hook based components are now supported by mobx-react, thus, there is no need for mobx-react-lite usage anymore (if that was your problem).
JUNE 2021 ANSWER
I've been experiencing this problem with the react-electron-boilerplate app.
Many plugins and libraries like Material-UI couldn't be used in my project because of this unfortunate error and after searching a lot, I could solve the problem:
I just upgraded the react and react-dom to their latest versions.
This command got the job done!
yarn add react#latest react-dom#latest
found this workaround for react-hot-loader while that PR to fix it is inbound.
Wrap the function that calls hooks in a React.memo, preventing a hot reload if it's unchanged.
const MyFunc = React.memo(({props}) => {...
Credit for solution:
https://github.com/gatsbyjs/gatsby/issues/9489
For fellow users of yarn workspaces, here's my situation and how I figured it out.
packages
foo
react#16.8.6
bar
react#16.10.1
The Facebook docs on Invalid Hook Call Warning say nothing about yarn workspaces, so I assumed my config was correct. But it wasn't. You can fix the error only by using the same version across all your packages.
In the example above, you have to bump the version of react from "foo" to 16.10.1, so that it matches the react version from "bar".
Bonus: see this discussion on GitHub for a beautiful collection of emotional baggage offloaded on the Internet.
Well in my Case i was calling useSelector inside useEffect !!
If you are using Create React App, you have to update "react-scripts" version also with react and react-dom version.
"react-scripts": "2.1.5",
"react": "^16.8.1",
"react-dom": "^16.8.1",
this combination works fine.
For me, this was occurring because I had a new version of react (16.8.6) and an old version of react-dom (16.6.1).
https://reactjs.org/warnings/invalid-hook-call-warning.html#mismatching-versions-of-react-and-react-dom
Upgrading both to #latest (16.8.6) fixed the error.
Check react and react-dom versions are strictly equal. Take care of the circumflex ^ symbol on versions.
"17.0.0" could not be the same as "^17.0.0"
npm - Carret Ranges: https://github.com/npm/node-semver#caret-ranges-123-025-004
React - Changelog: https://github.com/facebook/react/blob/main/CHANGELOG.md
That's one of the reasons to better install packages with -E or --save-exact
npm install --save --save-exact <package#vesion>
update package.json react-dom version as react

Import external Javascript libraries installed via npm in Meteor 1.3

I want to use the OpenSeadragon library in my Meteor app. As Meteor 1.3 provides support for npm modules, I have installed it via npm using meteor npm install openseadragon.
But now I am not sure how to user it. The OpenSeadragon docs only provides an example using the script tag.
The meteor docs tell us to use import like import moment from 'moment';. But how do I import openseadragon as I am pretty sure it doesn't use ES6 modules and doesn't export anything.
How can I use it using the npm import without loading the openseadragon.js as global for whole app?
The project's (poorly documented) API page states that
OpenSeadragon will also return an AMD module when required with a loader like Require.js.
Therefore, inside a client script, you can simply
import 'openseadragon'; // load globally
and it should give you the module constructor
Now, depending on what you are using, you may initialize your container from that constructor. For React container, this would look something like this :
import React, { Component } from 'react';
import { Random } from 'meteor/random';
import 'openseadragon'; // OpenSeadragon on global scope
export default class OpenSeedragonComponent extends Component {
constructor(props) {
super(props);
this.state = {
options: {
id: Random.id(), // container unique name
// other options here...
}
};
}
componentDidMount() {
this.initialiseWidgets();
}
componentDidUpdate() {
this.initialiseWidgets();
}
initialiseWidgets() {
this.viewer = OpenSeadragon(this.state.options);
}
render() {
return (
<div id={ this.state.options.id }
width={ this.props.width || '800px' }
height={ this.props.height || '600px' }
>
</div>
);
}
};
Note: at the moment of this writing, you will get an error when loading the .map file. Just ignore it, or open an issue with the project maintainer so he properly integrate the project with Meteor. Perhaps someone will write a react / meteor package wrapper for it...
A JS lib doesn't have to specifically use ES6 export keyword to expose symbols, as a matter of fact npm modules are still using CommonJS module.exports in their vast majority because even though package authors write their code in ES6 they publish them to npm using Babel.
In this specific case, you need to globally import the OpenSeadragon lib using import 'openseadragon'; somewhere in your client/ folder.
Then it will be available on window.OpenSeadragon.
Since the nice Yanick Rochon's answer does not seem to work in your case, note that you should still be able to load your library the "old fashion" way, using the [project_root]/client/compatibility/ special folder.
Any library in that folder will not be loaded in an independent scope by Meteor, but rather loaded "as is" like if it were through a classic <script> tag.
Then your OpenSeadragon object should become available on global scope.
As a side note, if you need simple image navigation and not the OpenSeadragon advanced features, you might be interested in trying Leaflet. It is lighter-weight but very stable and well maintained.

Categories

Resources