ReactRouter is undefined when bundling with webpack - javascript

I have a weird problem that seems related to webpack, but I am not sure. Here is the context, I am creating a front end using ReactJS, and I have a Java backend, so what I am trying to do is to compile and bundle all the JS using webpack with the config below.
const path = require("path");
module.exports = {
entry: {
main: path.join(__dirname, "src/js/index.js")
},
output: {
path: path.join(__dirname, "src/main/resources/static/js"),
filename: "bundle.js"
},
resolve: {
extensions: [".js", ".jsx"],
modules: [
path.join(__dirname, "src"),
"node_modules"
]
},
module: {
rules: [
{
test: /\.less$/,
loader: "less-loader"
},
{
test: /\.(js|jsx)$/,
loader: "babel-loader"
},
]
}
};
And here is the only JS file, with very basic display that is failing :
import PropTypes from "prop-types";
import React from "react";
import ReactDOM from "react-dom";
import ReactRouter, {Link} from "react-router";
document.addEventListener("DOMContentLoaded", function () {
console.log(React);
console.log(PropTypes);
console.log(ReactRouter);
console.log(Link);
console.log(document.getElementById("root"));
ReactDOM.render(<Link to="/">Home</Link>, document.getElementById("root"));
});
I've installed all npm required packages, webpack is running without errors, but when I open the page in the browser, there is an error + warning in the console.
Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: undefined. You likely forgot to export your
component from the file it's defined in.
Error: Element type is
invalid: expected a string (for built-in components) or a
class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in.
I found that it is because Link and ReactRouter are undefined, but I don't understand how it's possible since they are imported and the package is installed.
Do you have any idea on how to solve the problem ?

In addition to the first comment on your post, you might wanna check out which version of React-Router you have. In the newest version, { Link } is a part of the "react-router-dom" package, and you can replace "react-router"'s { Router } with "react-router-dom"'s { BrowserRouter }.
React-Router-Dom is part of the React-Router package you installed (if it's a newer version), so all you need to do is replace React-Router with { BrowserRouter } and "react-router/" with "react-router-dom".

Related

vue.config.js configureWebpack not used in unit tests (vue 3)

In my vue config I have the following:
configureWebpack: {
resolve: {
alias: {
react: path.resolve(__dirname, 'composition/react'),
hooks: path.resolve(__dirname, 'composition'),
},
},
},
In my component I have the following:
import { useEffect, useState } from 'react';
This is so I can re use some of the Vue code in React projects. This works when running and building the project but not when testing. When unit testing I get the error: Cannot find module 'react' from 'useCategories.js', the above import is from useCategories.
The following is in the jest.config.js:
module.exports = {
preset: '#vue/cli-plugin-unit-jest',
transform: {
'^.+\\.vue$': 'vue-jest'
}
}
If unit testing in vue is ignoring values from vue.config.js then how can I set the webpack path resolve values for testing. I would rather not repeat these values but if it's a JavaScript file I guess I can import it from the same file in different configs.
Webpack isn't used in Jest, this would make module testing impractical, so Webpack config cannot affect anything.
As the documentation explains, it's necessary to provide module mapping in Jest config as well, e.g.:
moduleNameMapper: {
'^react$': '<rootDir>/composition/react',
...

Trying to build react library but keep getting Error: Element type is invalid: expected a string

Hi guys Im working on my first React library:
Here it is:
https://github.com/HunterJS-bit/react-mini-contextmenu
But when I try to npm install it, I get error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
I do not know what to change next I tried changing adding default export in my index.ts
Like this:
import ContextMenu from './components/ContextMenu';
export default ContextMenu;
But it is still not working as expected, getting same error :/
has anyone had simmilar issue because I do not see how can I solve this
Try doing this:-
import { default as ContextMenu } from './components/ContextMenu';
export default ContextMenu;
or
Check for your webpack config's output path. That should be the
problem if the above solution doesn't work.
Try adding this to you rules:-
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
exclude: /node_modules/,
}
OR
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
You can try both too.
Try this
in your index.ts
export * from './components/ContextMenu';//to reexport the name exports
export {default} from './components/ContextMenu';// to reexport the default exports
Instead of importing and exporting again
I think that you are exporting a element instead of a component. Export the component instead.

Build React components library with Webpack 4

I'm currently building a library of React components and bundling it with Webpack 4.
Everything works just fine from building the library's bundle to publishing it on an npm registry.
But then, I'm not able to import any of its components in an other React application and get this error message at runtime:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
And here is the related code:
A dumb component from my components library:
button/index.js
import React from "react";
const Button = () => <button>Foobar</button>;
export { Button };
The main entry point of my library index.js:
import { Button } from "./src/components/Button";
export { Button };
My Webpack config webpack.config.js:
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: "./index.js",
plugins: [new CleanWebpackPlugin()],
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
output: {
filename: "index.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "commonjs",
library: ""
}
};
And finally, the import of this component in an other application:
import { Button } from "my-design-system";
I guess I'm missing something in my Webpack config or one of the property may be wrong, but after reading multiple posts and tutorials, I can't figure which one.
You're exporting your library as commonjs and trying to import it via import/export syntax. You should change your output to
output: {
filename: "index.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "umd",
library: "my-design-system"
}
Found a lot of info here: https://webpack.js.org/guides/author-libraries/
What I would do is to export your components as default and then re-export as named from index.js:
/// Button.js
import React from "react";
const Button = () => <button>Foobar</button>;
export default Button ;
// index.js
export { default as Button } from "./src/components/Button";
Then you can do
import { Button } from "my-design-system";
Also make sure you have main set up, pointing to your index.js, in your design system's package.json
Additionally, if you still want to have named exports in some of your components, you can export everything from that component file:
//index.js
export * from "./src/components/ComponentWithNamedExports";
Either way you will make sure there's always one point of export for all your components.
EDIT: As noted in by Maaz Syed Adeeb, you have wrong libraryTarget in your config. I'd remove both libraryTarget and library from there.

How to use React components from local npm package

I'm trying to create an npm package with some React components that I use for virtually all of my projects. Here's the folder structure and file contents:
/
dist/
bundle.js
src/
MyComponent.jsx
index.js
package.json
webpack.config.js
MyComponent.jsx
import React, { Component } from 'react';
class MyComponent extends Component {
render() {
return (
<p>Hello, world!</p>
);
}
}
export default MyComponent;
index.js
// eventually there will be more components imported/exported here
import MyComponent from './MyComponent.jsx';
exports.MyComponent = MyComponent;
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: './dist',
filename: 'bundle.js'
},
// some loaders...
};
package.json
{
"name": "my-library",
"files": [
"dist",
"src"
],
"main": "dist/bundle.js",
// the usual stuff...
}
This is my understanding of the process. First, I build the src files with webpack. This looks at /src/index.js, imports the MyComponent class, then exports it, making it available as MyComponent. This is all added to a bundle.js file in /dist.
Next, I pack the module with npm pack. This creates an archive file with the /src and /dist directories in it.
Then I go over to my other project and run npm install ../path/to/archive/file. This adds the module to my node_modules directory. The problem is that when I try to import and use MyComponent...
import React, { Component } from 'react';
import MyComponent from 'my-library';
class App extends Component {
render() {
console.log(<MyComponent />);
return (
<MyComponent />
);
}
}
export default App;
...and render that component, I get this warning and error:
Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `App`.
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `App`.
The output of the console.log is a React object, but the type is Object, which seems like what the warning is alluding to (it should be a string instead, I guess).
Any idea what I'm missing?
EDIT:
Well, I'm closer. I added library options to my webpack config:
output: {
library: 'my-library',
libraryTarget: 'umd'
}
...and then I was able to use the component like this:
import MyLibrary from 'my-library';
const MyComponent = MyLibrary.MyComponent;
But I don't want to have to do that for every component. My goal is this:
import { MyComponent, MyOtherComponent } from 'my-library';
You have to export your component from the component index.js file like shown below
import MyComponent from './MyComponent.jsx';
import MyOtherComponent from './MyOtherComponent.jsx';
export {
MyComponent,
MyOtherComponent
}
Then in your Main project, Import them using
import { MyComponent, MyOtherComponent } from 'my-library';

Objects are not valid as a react child (In Internet explorer 11 for React 15.4.1)

Objects are not valid as a React child (found: object with keys {$$typeof, type, key, ref, props, _owner, _store}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of App.
AppContainer :
const mapDispatchToProps = (dispatch) => {
return {
}
}
}
}
Component:
class App extends Component {
render() {
return (
);
}
}
Above is my render function for app.js. This Code is working fine in google chrome, but when coming to Internet explorer It is not working and it is throwing the above error.
A problem since React 15.4 with IE11
If you still have this issue, you may have a look at this react issue #8379 about React 15.4 and IE11.
I had the same problem with webpack dev mode / IE11 / React 15.4, and it seems that React and ReactDom each use their version of a Symbol polyfill (this is new with 15.4):
Somehow react and react-dom no longer "agree" on the $$typeof value
which should be typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103.
Solution
I've resolved this issue by reordering polyfill and react / react-dom to be sure that the polyfill Symbol is loaded before React and ReactDom's Symbol... Now they "agree" on $$typeof value.
Example solution for webpack:
entry: [
'babel-polyfill', // Load this first
'react-hot-loader/patch', // This package already requires/loads react (but not react-dom). It must be loaded after babel-polyfill to ensure both react and react-dom use the same Symbol.
'react', // Include this to enforce order
'react-dom', // Include this to enforce order
'./index.js' // Path to your app's entry file
]
In my case with React Native we dragged this mysterious bug for weeks appearing just on Android builds without an attached debugger.
The culprit was an
import 'core-js'
on our root component, it seems the polyfill was messing things up
The solution was to simply remove it as it's no longer necessary in my case
Relevant portion of package.json
"react-native": "0.44.2",
"react": "16.0.0-alpha.6",
My issue was babel-polyfill needed to be above my react-hot-loader includes. React and react-dom needed to preceed babel-polyfill in the webpack entry for reasons described by this comment:
https://github.com/facebook/react/issues/8379#issuecomment-263962787.
Looked like this:
dev:
entry: [
'babel-polyfill',
'react-hot-loader/patch',
`webpack-dev-server/client?${localhost}:${PORT}`,
'webpack/hot/only-dev-server',
PATHS.app
]
production:
entry: [
'babel-polyfill',
'react',
'react-dom',
PATHS.app
]
Previously...
dev:
entry: [
'react-hot-loader/patch',
`webpack-dev-server/client?${localhost}:${PORT}`,
'webpack/hot/only-dev-server',
'babel-polyfill',
PATHS.app
]
production:
entry: [
'babel-polyfill',
PATHS.app
]
I'm using core-js polyfills in my project.
The solution that ended up working for me was to add this line to the top of my src/index.js file:
import 'core-js/es/symbol'
My Issue was same and was using React Native and was testing the android app on ABD device/emulator.
After seeing suggestions from above to remove import 'core-js' and to add
entry: [
'babel-polyfill', // Load this first
'react-hot-loader/patch', // This package already requires/loads react (but not react-dom). It must be loaded after babel-polyfill to ensure both react and react-dom use the same Symbol.
'react', // Include this to enforce order
'react-dom', // Include this to enforce order
'./index.js' // Path to your app's entry file
]
to android/app/build.gradle file, my issue was not resolved As i didn't had any of the import statement like import 'core-js' or import 'babel-polyfill' initially in my code.
**
Solution:
**
Insted of removing import statement i added the import 'core-js'; to my root directory which was index.js. With manually adding the library through command Prompt/Terminal.
This solved my issue.Hope this helps.
In my case I started my project with react-slingshot and this is a solution that worked for me:
# from https://github.com/facebook/create-react-app/tree/master/packages/react-app-polyfill
$ npm install react-app-polyfill --save
Then in the webpack.config.js file
entry: [
'react-app-polyfill/ie11', // <==== Important line and must be loaded before you code does
path.resolve(__dirname, 'src/index.js')
],
target: 'web',
mode: 'development',
plugins: [
...
You can see the full documentation here: react-app-polyfill
Hope this also works for you guys!

Categories