Why do I need import React statement even if I don't use React explicitly? - javascript

I have an React App, following is JavaScript code
import React from 'react';
import ReactDOM from 'react-dom';
const App = function(){
return <div>Hi</div>
}
ReactDOM.render(<App />, document.querySelector('.container'));
And the HTML file is as following.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/style/style.css">
<link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/48938155eb24b4ccdde09426066869504c6dab3c/dist/css/bootstrap.min.css">
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAq06l5RUVfib62IYRQacLc-KAy0XIWAVs"></script>
</head>
<body>
<div class="container"></div>
</body>
<script src="/bundle.js"></script>
</html>
The question I don't understand is that if I remove import React from 'react', it will show error message like below.
Uncaught ReferenceError: React is not defined
But I don't use React in my code explicitly anywhere, why would it show a message like this. Can anyone tell me what's going on under the hood?
UPDATE:
Not exactly the same question with this one, since what I have in my code is just an individual component, not involving any parent component.

Using JSX (<App />) is just a syntatic sugar for React.createElement().
So when your code is transpiled to pure javascript, references to React will appear there, so you need the import for that.
So yes, you're using it, although you don't see it
See what is your code transpiled to here
'use strict';
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var App = function App() {
return React.createElement(
'div',
null,
'Hi'
);
};
_reactDom2.default.render(React.createElement(App, null), document.querySelector('.container'));

Related

Unexpected token '<' when trying to load my webcomponent in html

so im trying to create a react webcomponent. I wrap it and on VSCode looks fine, but when I'm trying to load it, it gives me the error: Unexpected token '<' on the line:
ReactDOM.render(<Counter/>, mountPoint);
Does anyone know why and how to fix it? thanks
This is my WebComponent:
import React from 'react';
import * as ReactDOM from 'react-dom';
import Counter from './counter';
class CounterWC extends HTMLElement {
connectedCallback() {
// Create a ShadowDOM
const root = this.attachShadow({ mode: 'open' });
// Create a mount element
const mountPoint = document.createElement('div');
root.appendChild(mountPoint);
// You can directly use shadow root as a mount point
ReactDOM.render(<Counter/>, mountPoint);
}
}
customElements.define('counter-wc', CounterWC)
And this is my html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-9" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>React webcomponent:</h1>
<counter-wc></counter-wc>
<script type="module" src="./counterWC.js"></script>
</body>
</html>
Re: comments
The fact that you name your file *.js doesn't mean it is JavaScript
ReactDOM.render(<Counter/>, mountPoint); is JSX, not JavaScript, it needs to be converted in a Build step to JavaScript.
Or do not use React at all:
class CounterWC extends HTMLElement {
constructor(){
super()
.attachShadow({mode: 'open'})
.append(this.div = document.createElement('div'));
}
connectedCallback() {
this.div.innerHTML = `Am I a counter?`;
}
}
customElements.define('counter-wc', CounterWC);
<counter-wc></counter-wc>

Next.js An update to Image inside a test was not wrapped in act(...)

I created a basic NextJS app using create-next-app then added Jest for testing. However, I am getting the error "An update to Image inside a test was not wrapped in act(...)" in my Jest test. It seems to be something to do with the Image component of NextJS updating after render, but I'm not quite sure what's the best way to test with it. I've included the Jest test and the problematic part of the component here:
import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
const Home: NextPage = () => {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</main>
</div>
)
}
export default Home
import React from 'react'
import { render, act } from '#testing-library/react'
import { axe } from 'jest-axe'
import Home from '#/pages/index'
it('should demonstrate this matcher`s usage with react testing library', async () => {
const { container } = render(<Home/>)
const results = await axe(container)
expect(results).toHaveNoViolations()
})
The error message also points to code at node_modules/next/client/image.tsx:353:3 being problematic, and looking at the source, that part seems to be a useLayoutEffect hook in the Image component...
Figured it out. Followed the solution mentioned at this article and it worked.
Install react-intersection-observer
In the Jest config (jest.config.js):
Add react-intersection-observer/test-utils' to the setupFilesAfterEnv
Create a jest.setupFiles.js and add to setupFiles in the in the customJestConfig
{
...
setupFiles: ['<rootDir>/jest.setupFiles.js'],
setupFilesAfterEnv: [
'<rootDir>/jest.setup.js',
'react-intersection-observer/test-utils',
],
...
}
In jest.setupFiles add:
import { defaultFallbackInView } from 'react-intersection-observer'
global.IntersectionObserver = jest.fn()
defaultFallbackInView(false)
And the error should go away. :)

How to create and render a React Component after babelify/transpiling?

I have a hello world react component that is written in JSX, transpiled with babel, and then included in the hello.html template of a Flask app. What I have working is creating and rendering the component before transpiling as such:
const hello = <Hello name="world" />;
ReactDOM.render(hello, document.getElementById('hello'));
How can I do those two steps in a <script> tag in my hello.html template? My goal is to be able to pass that name variable from the template to the component and then render it.
A little more context:
The JSX hello.js looks like this:
import React from 'react';
import ReactDOM from 'react-dom'
import { render } from 'react-dom'
class Hello extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div>Hello {this.props.name}!!!</div>
)
}
}
//The following works:
//const hello = <Hello name="world" />;
//ReactDOM.render(hello, document.getElementById('hello'));
hello.html looks like this:
<html>
<head>
</head>
<body>
<div>ASDF</div>
<div id="hello"></div>
</body>
{# The following line is a post babelify (transpiled) hello.js #}
<script type="text/javascript" src="{{ url_for('static', filename='js/hello.js') }}"></script>
<script type="text/javascript">
{#
What goes here? The code in the above section does not work.
The transpiled code defines a "var Hello = /*#__PURE__*/ function (_React$Component) { ...".
const hello = Hello(); does not throw an error, but also does not render or pass an argument.
hello.render(); is also something that I have tried, along with arguments for div/id to render in and name.
#}
</script>
</html>
Correction: Calling Hello() does not throw an error if the script is text/babel, in which case the script probably isn't doing anything.
The Flask route looks like this:
#app.route(u'/')
def index():
return render_template(u'hello.html', name="universe")
Two ways you can pass variables from your server application to react component:
Use the html data-variable prop.
Create a global variable. Something like window.variable
Then you should be able to access variable as a props like props.variable in your react-component.
My recommended approach I would take is to use a bundler such as SystemJS (version 2), and you will have something like the following:
<!DOCTYPE html>
<html>
<head>
<script src="node_modules/core-js-bundle/minified.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script type="systemjs-importmap" src="systemjs.imports.json"></script>
<script src="node_modules/systemjs/dist/system.min.js"></script>
<script src="node_modules/systemjs/dist/extras/named-exports.min.js"></script>
<script>
System.import('../.playground/index.js').catch(function (err) { console.error(err); });
</script>
</head>
<body>
<div>ASDF</div>
<div id="hello"></div>
</body>
</html>
And index.js will look something like this
ReactDOM.render(
(< Hello/>),
document.getElementById('app')
);
Then your systemjs-importmap will look like this
{
"imports": {
"react": "../node_modules/react/umd/react.production.min.js",
"react-dom": "../node_modules/react-dom/umd/react-dom.production.min.js",
// ... other named exports you want to add like the Hello component here
}
}

How to add Firepad to a reactjs app

I am trying to add Firepad to a reactjs application. Here is my code
import React, { Component } from "react";
import firebase from "firebase";
import Firepad from "firepad";
import CodeMirror from 'codemirror';
class CourseNotes extends Component {
componentDidMount() {
var firepadRef = firebase.database().ref();
var codeMirror = CodeMirror(document.getElementById('firepad'), { lineWrapping: true });
var firepad = Firepad.fromCodeMirror(firepadRef, codeMirror, {
richTextShortcuts: true,
richTextToolbar: true,
defaultText: 'Hello, World!'
});
}
render() {
return (
<div>
<div>testing </div>
<div id="firepad" />
</div>
);
}
}
export default CourseNotes;
I've tried a few things to no success. Other solutions on stack overflow include adding these script tags to the html but that didn't seem to work.
<!-- CodeMirror -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.17.0/codemirror.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.17.0/codemirror.css" />
<!-- Firepad -->
<link rel="stylesheet" href="https://cdn.firebase.com/libs/firepad/1.4.0/firepad.css" />
<script src="https://cdn.firebase.com/libs/firepad/1.4.0/firepad.min.js"></script>
Any advice would be much appreciated.
For anyone else who comes accross this question. I eventually figured it out.
The issue was the way create-react-app builds itself.
To use imported scripts just prepend "window." before the firebase and codemirror functions. IE:
var codeMirror = window.CodeMirror(document.getElementById('firepad'), { lineWrapping: true });
Use these npm packages - brace, react-ace, firebase, firepad.
Since firepad needs aceto be present globally, assign brace to global var
like(not the best way, but works) before importing firepad
import brace from 'brace';
global.ace = brace;
global.ace.require = global.ace.acequire;
import Firepad from 'firepad';
Use ref to get instance of ReactAce and initialize it in componentDidMount using:
new Firepad.fromACE(this.firepadRef, this.aceInstance.editor, options);
Similarly for CodeMirror editor.
Hoping, this would be of some help.

JavaScript ReferenceError: $ is not defined

I have an html file that looks like this:
<!DOCTYPE html>
<html>
<head>
<title>AppName</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
</head>
<body>
<div id="container"></div>
<script src="/bundle.js"></script>
</body>
</html>
And I have a javascript file that contains this:
EDIT: included jQuery via npm, and it seems to have worked.
export function getData(arg, callback) {
var $ = require('jQuery'); // This line was added via EDIT above.
$.ajax({
type: "GET",
url: "/get_data",
data: {data: arg},
success: callback
});
}
When I go to my page and execute the function, I eventually get this error:
Uncaught ReferenceError: $ is not defined
at Object.getData (http://localhost:1234/static/bundle.js:21665:6)
Based on the questions/answers I've seen on SOF, it seems like the solution was to include the jquery script in my html file.
Any ideas what I might be doing wrong?
EDIT: As per request, here is my react index.js file. The error is coming from within the searchApi.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import SearchBar from './components/SearchBar';
import * as searchApi from './api/searchApi';
class App extends React.Component {
constructor() {
super();
this.getData = this.getData.bind(this);
this.processData = this.processData.bind(this);
}
getData(data) {
searchApi.getData(data, this.processData);
}
processData(payload) {
console.log(payload);
}
render() {
return (
<div>
<SearchBar getData={this.getData}/>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);

Categories