First of all I want to say that I'm new to javascript and react world so sorry in advance if my question is trivial but I can't figure out this situation. I will update the post if needed.
I want to migrate my current application to single page application. I have 3 main pages PageA, PageB and PageC (in react I have 3 main components). I want to be able to switch between these 3 pages/components. Lets say that I have this LogoText which is the component that represents the logo of the site. I want to have it in all other components (including the PageA) and when I click on it I want to render the main page ( PageA ).
So I'm trying to build a it with react and webpack . In this simple example given below I have a main page component MainPage.js which is parent component for all components that should be in the main page and a LogoText component which should render the MainPage component when someone click on it. When all this components are in one file and I don't use require() everything is working perfectly but when I break down my app into modules using require() and package it with webpack I get strange behaviour. I can load the MainPage component and the LogoText component is displayed correctly in the MainPage but when I click on the LogoText I get "Uncaught Invariant Violation: Element type is invalid" exception (click for screenshot)
first exception:
react.js:18798 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).
second exception:
react.js:18354 Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
I have the following 3 classes:
main.js:
var MainPage = require("./MainPage.js")
ReactDOM.render(
<MainPage />,
document.getElementById('content')
);
MainPage.js:
var LogoText = require("./LogoText.js")
var MainPage = React.createClass({
render: function() {
return (
<div>
Hello page,
<LogoText />
</div>
);
}
});
module.exports = MainPage;
LogoText.js
var MainPage = require("./MainPage.js")
var LogoText = React.createClass({
changePage: function(e) {
ReactDOM.render(
<MainPage />,
document.getElementById('content')
);
},
render: function() {
return (
<span onClick={this.changePage}>logo</span>
);
}
});
module.exports = LogoText;
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React Tutorial</title>
<!-- Not present in the tutorial. Just for basic styling. -->
<link rel="stylesheet" href="css/base.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.16/browser.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.min.js"></script>
</head>
<body>
<div id="content"></div>
<script src="scripts/bundle.js"></script>
</body>
</html>
UPDATE 1: Here is my webpack.config.js:
module.exports = {
entry: "./src/scripts/main.js",
output: {
path: "./src/scripts",
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" },
{ test: /\.js$/, loader: 'jsx-loader?insertPragma=React.DOM&harmony'},
]
},
externals: {
//don't bundle the 'react' npm package with our bundle.js
//but get it from a global 'React' variable
'react': 'React'
},
resolve: {
extensions: ['', '.js', '.jsx']
}
};