Render Transpiled ES6 in CSHTML - javascript

I have
Tutorial.jsx
class ShoppingList extends React.Component {
render() {
return (<div>Milk</div>);
}
}
export default ShoppingList;
webpack.config.js
module.exports = {
...
output: './React/bundle.js',
...,
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: ['es2015', 'react'],
}
}
]
}
}
In my CMD prompt, when I run webpack -w everything is green and I see my bundle.js file appearing where it should, in the React folder. Opening it, I see
...
var ShoppingList = function (_React$Component) {
...
}
...
so it looks like that's all good.
Now I want to render ShoppingList in my _Layout.cshtml file.
Question: How do I do this? I've tried all methods below and get React errors all the time about invalid parameter type, or passing in the wrong element, or whatever. My CSHTML is below.
<div id="content1">render here</div>
....
<script src="~/React/bundle.js"></script>
<script>
ReactDOM.render("ShoppingList", document.getElementById("content1"));
ReactDOM.render(ShoppingList, document.getElementById("content1"));
ReactDOM.render(<ShoppingList />, document.getElementById("content1"));
</script>
Can someone please let me know if
It's possible to NOT have a ReactDOM.render() inside the JSX file and,
It's possible to do what I want to do which is render my ShoppingList in CSHTML
The best results I've got so far is to see ShoppingList in my DOM explorer but no HTML was actually rendered. It came out <shoppinglist ...></shoppinglist> which appears wrong to me.
Thanks.

You should have this inside your entry file:
import ShoppingList from 'path-to/ShoppingList';
ReactDOM.render(<ShoppingList />, document.getElementById("content1"));
In the CSHTML page the additional script tag is not required.
Your original example does not work because:
ShoppingList is not exposed globally (exporting as default does not make it global).
JSX syntax (<ShoppingList />) needs to be transpiled before it can be used in HTML page.
If you really need to use a component within a CSHTML page, you can make the component global:
window.ShoppingList = ShoppingList
inside the file that defines the component.
And use vanilla javascript instead of JSX syntax:
ReactDOM.render(React.createElement(ShoppingList), document.getElementById("content1"))

Related

Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type. <!DOCTYPE html>

I am trying to import a static about.html page inside a react
component but getting this error. I want to import multiple static HTML pages.
This is my component
import React, { Component } from 'react';
import Page from './about.html';
var htmlDoc = {__html: Page};
export default class MyComponent extends Component {
constructor(props){
super(props);
}
render(){
return (<div dangerouslySetInnerHTML={htmlDoc} />)
}}
If you want to include static html in ReactJS. You need to use html-loader plugin if you are using webpack to serve your react code.
First of all you need to install html-loader plugin. Open your terminal and run following command:
npm install --save-dev html-loader
Then open your webpack configuration file and add following code:
{
modules: {
loaders: [
{ test: /\.html$/, loader: 'html-loader' }
]
}
}
Now, in your react code do following changes:
var htmlContent = require('path/to/html/file.html');
export default function MyComponent() {
return (
<div dangerouslySetInnerHTML={ {__html: htmlContent} } />
);
}
That is it. Now you may use static html files to load your html files in react.

Why can't we invoke ReactDOM or React directly in the browser?

I'm new to React and I'm still trying to wrap my head around how it works.
I understand that in our React code before "compiling" we can use React.createElement and ReactDOM.render to do all sorts of stuff but after the code is compiled and run on the client, suppose I wanted to dynamically create a new DOM node with one of my components.
Adding some code for further explanation
This is my index.js:
import React from 'react'
import ReactDOM from 'react-dom'
class HelloWorld extends React.Component {
render() {
return (
<div>
Hello World!
</div>
)
}
}
ReactDOM.render(
//React Element,
<HelloWorld />,
//where to render the Element to
document.getElementById('hello')
)
This works fine. However when I try dynamically adding the component "live" via the devtools console and type React.createElement, I get:
React is not defined
The same with ReactDOM. Are they not available via the console? There's probably something missing in my understanding and I'm thinking about this wrong but how exactly is React and ReactDOM not defined if my index.js was able to invoke ReactDOM.render?
Thanks!
React and ReactDOM can be used in the console if:
You export, what you need in the global scope, from webpack's entry point. For example:
export {React, ReactDOM, LeaveStats }
The bundle generated from webpack is included in the HTML page via a non-module script
Webpack is configured to output a "library" like so:
module.exports = {
entry: './app/LeaveStats.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
library: 'ReactApp' // <-- this will allow us access to whatever is exported in ./app/LeaveStats.js
},
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader' },
]
},
mode: 'development'
}
You can then have access to React, ReactDOM and LeaveStats from the global scope e.g.:
ReactApp.ReactDOM.render(
ReactApp.React.createElement(ReactApp.LeaveStats),
document.getElementById("mydiv")
)
Not that I would really use this, but kind of helped my understand a few things along the way reaching to this point.

How to add examples a component with dependencies in react-styleguidist

I would like to document a ButtonGroup component rendering Button components within it using `react-styleguidist'.
I have a styleguidist webpack config which looks like this:
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader'
}
],
exclude: /node_modules/
}
]
},
devtool: 'cheap-module-eval-source-map'
}
I know that I dont need to define commonly used loaders and plugins because styleguidist already adds them internally
Inside the src/components/, the directory structure for allowing styleguidist to pick up my components looks a little like this:
Button
index.js
Readme.md
ButtonGroup
index.js
example.js (created for Case II after Case I failed)
Readme.md
Case I
In my Readme.md within the ButtonGroup directory:
```jsx
const Button = require('../index')
<ButtonGroup>
<Button type='primary' size='lg'>Hello, World</Button>
<Button type='primary' size='lg'>Hello, Doctor</Button>
</ButtonGroup>
```
When I do that, my styleguide has an error that says:
SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag (5:2)
Case II
I have tried enclosing the information in an example.js inside ButtonGroup directory as illustrated above, the file contains:
import React from 'react'
const ButtonGroup = require('./index')
const Button = require('../index')
export default function ButtonGroupExample (props) {
return (
<ButtonGroup>
<Button>Hello, World</Button>
<Button>Hello, Doctor</Button>
</ButtonGroup>
)
}
Now the example component is imported into the Readme.md:
```jsx
const Example = require('./example')
(<Example />)
```
which throws the error:
TypeError: require(...) is not a function
I know that I dont need to define commonly used loaders and plugins because styleguidist already adds them internally
This is not true. Styleguidist doesn’t add any loaders to your code.
SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag (5:2)
Most likely you need a semicolon after ;. And probably you don’t need to require a Button component. It depends on your style guide config and whether you want to show your Button component in a style guide.
If you want to show both components in a style guide, point Styleguidist to all you components: components: 'src/components/**/index.js'.
If you want to hide some components from a style guide but be able to use them in examples, enable skipComponentsWithoutExample option an use require option to load your components:
// styleguide.config.js
module.exports = {
skipComponentsWithoutExample: true,
require: [
path.resolve(__dirname, 'styleguide/setup.js')
]
}
// styleguide/setup.js
import Buttom from './src/components/Button';
global.Button = Button;
Case II
I’m not sure what you’re trying to do here.

React Import Icons / Images in bulk

I have 100's of Icons and Images to be imported. Is there any way to eliminate writing so many import statements at the top of the page? I was thinking to write a import statements in a separate file and embed that at the top.
import basicAmenitiesIcon from '../../../../images/icons/wifi-sign.png';
import parkingIcon from '../../../../images/icons/parking.png';
...
Any other way of solving it? I'm using webpack and here is the config:
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
]
}
Yes, it is posible, see my answer here: https://stackoverflow.com/a/41410938/646156
var context = require.context('../../../../images/icons', true, /\.(png)$/);
var files={};
context.keys().forEach((filename)=>{
files[filename] = context(filename);
});
console.log(files); //you have file contents in the 'files' object, with filenames as keys

problems with babel react preset and react-dom

I'm using webpack and babel to pre-process my jsx files to javascript. My configuration looks like this:
Webpack.config.js
module.exports = {
entry: "./react/main.jsx",
output: {
path: __dirname,
filename: "./public/javascripts/app.js"
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}
]
}
};
./react.main.jsx
import { render } from 'react-dom'
import HelloWorld from './components/helloworld.jsx'
render(<HelloWorld />,document.body);
./react/components/helloworld.jsx
import React from 'react'
class HelloWorld extends React.Component {
static render() {
return (
<div>
<h1>Hello World!</h1>
<p>This is some text</p>
</div>
);
}
}
export default HelloWorld;
When I run webpack I keep getting the error React is not defined at this line in app.js
(0, _reactDom.render)(React.createElement(_helloworld2.default, null), document.body);
If I specifically include react in my main.jsx file that error goes away and then the error is
Uncaught Invariant Violation: _registerComponent(...): Target container is not a DOM element. pointing to the null value as the second parameter of React.create element in app.js
I'm sure it's something I'm missing or doing wrong, but I don't know what it is.
Add this line of code into your main.jsx file.
import React from 'react'
as a react-dom uses react, but the primary reason is that the file contains JSX and JSX is just converted to React.createElement calls - Felix Kling
From upgrade Guide React v0.14
Passing document.body directly as the container to ReactDOM.render now
gives a warning as doing so can cause problems with browser extensions
that modify the DOM.
So change your markup to
<body>
<div id="app"></div>
</body>
After that you can render your component to the div tag
render(<HelloWorld />,document.getElementById('app'));
Thanks
Thanks for the help everyone. I didn't realize that react-dom didn't require 'react' on its own. at any rate, the other half of the issue was the placement of app.js after it was compiled. I put it at the bottom after the body and everything worked perfectly. I did get a warning about document.body so I'll change that to use a div instead.

Categories

Resources