I made simple Reactjs that has index.js and App.js. App.js defines App component. index.js imports App.js and uses App component. However, index.js receives "App is undefined error". How can this be?
index.js:
import React from "react"
import '../components/App.js';
export default class Home extends React.Component {
render() {
return (
<div>
<p>Welcome to donghwankim.com!</p>
<p>Powered by Gatsby</p>
<App />
</div>
)}
}
It imports App.js:
/*global kakao*/
import React, { Component } from 'react';
import '../css/App.css';
class App extends Component {
componentDidMount() {
const script = document.createElement('script');
script.async = true;
script.src = "https://dapi.kakao.com/v2/maps/sdk.js?appkey=ee494d4410cf578c0566203d2f487eb9";
document.head.appendChild(script);
script.onload = () => {
kakao.maps.load(() => {
let el = document.getElementById('map');
let map = new kakao.maps.Map(el, {
center: new kakao.maps.Coords(523951.25, 1085073.75)
});
});
};
}
render() {
return (
<div className="App" id="map"></div>
);
}
}
export default App;
and it gives the following error during development:
12:8 error 'App' is not defined react/jsx-no-undef
From what I learned, shouldn't imported App.js define App? Why is it undefined?
Thank you.
This line:
import '../components/App.js';
...doesn't actually import anything, it just runs the code in App.js. To import the default export, you do so explicitly:
import App from '../components/App.js';
// ^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−
You may now be wondering: "But why doesn't importing App.js and running its code create App automatically?" Because modules don't create globals (not unless you go out of your way to do so)., and there are no automatic imports. One of the key aspects of modules is that you explicitly define the links between them. One benefit of doing that is that when you're using a library with lots of functionality exported by a single module, the browser (or your bundler) can tree-shake it — keeping only the parts you actually use, and discarding the rest (the dead wood that fell out when it shook the tree).
Related
I'm developing a React App and pushing the files using Clasp to my google scripts webapp. Parcel.js is being used for compiling. Here's a basic React App that works:
index.js
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('app');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App />);
App.js
//app.js
const App = () => {
return <div>Hello App!</div>
}
export default App
But as soon as I add one #mui/material/ import into App.js I'm getting an error.
import Button from "#mui/material/Button"
const App = () => {
return <div>Hello App!</div>
}
export default App
Notice that I'm not even using the Button. Locally there's no error but when running on google scripts webapp, I get a console error:
Uncaught SyntaxError: missing ) after argument list
Obviously, Parcel is not compiling something correctly but I can't figure it out. Thanks in advance for the help.
New to React JS, props validation practise as follows:
import React from 'react';
import PropTypes from 'prop-types';
class App extends React.Component {
render() {
return (
<div>
<h3>String : {this.props.propstring}</h3>
</div>
);
}
}
App.propTypes = {
propstring : PropTypes.string
}
App.defaultProps = {
propstring : "My Name"
}
export default App;
import React, { component } from 'react';
import ReactDOM from 'react-dom';
import App from './AppProp.js';
ReactDOM.render(<App />,document.getElementById('root'));
Getting an error as:
TypeError: Class extends value undefined is not a constructor or null.
What am I missing here and how can I resolve the above error?
There are 2 possible problems. Most probably you're importing { component }(like you do in your index file, which is wrong), instead of { Component } somewhere in your code and trying to extend component which doesn't exist.
The other reason is that you might be circularly importing classes, but I doubt it. Also, is your file called AppProp.js?
Post the stack trace and it would also help if you post all the components you're using. Post your package.json as well, as you might be using wrong absolute paths.
The code is perfectly fine. I executed it on my local machine and it ran fine.
The only issue you may be facing is to with
circularly importing classes, which is apparently a limitation
Know more from the resource:
https://esdiscuss.org/topic/how-to-solve-this-basic-es6-module-circular-dependency-problem
Hi guys I'm trying to make a jigsaw website using react. I found a library called snapfit.js that can generate simple jigsaws from a png file. The problem is that I need to get this script working in a react component.
Currently I import the snapfit.js file in my index.html and when I open the console in chrome I can see that snapfit got added to the window (snapfit.window). I cant seem to find a way to make use of it in my react component though.
Currently I have:
import * as React from 'react'
import mole from '../assets/mole.png'
import {Helmet} from 'react-helmet'
import Button from 'react-bootstrap/Button'
export class PuzzelSnapfit extends React.Component {
render(){
return (
<div>
<h2>Demonstration</h2>
<div><img src={mole} onLoad={alert(this)} />
</div>
</div>
);
}
}
export default PuzzelSnapfit
I also tried using react-helmet like this:
<div><img src={mole} onLoad={window.snapfit.add(this)} />
When I try executing it that way I get a toUpperCase of undefined error, so it seems that this is undefined. I also tried loading the image into state but then I also get a undefined error.
Any help would be appreciated because I really dont know what else I could try except for maybe injecten a html file into my component but that also has its downsides.
You can import external scripts into your react js files by using the import statement.
example (your file where you want to use snapFitFunction1() and snapFitFunction2()):
import * as React from 'react'
import mole from '../assets/mole.png'
import {Helmet} from 'react-helmet'
import Button from 'react-bootstrap/Button'
import { snapFitFunction1, snapFitFunction2 } from './snapfit.js';
...
In your snapfit.js file, you should have a export statements for snapFitFunction1, and snapFitFunction2.
example (snapfit.js):
function snapFitFunction1() {
console.log('Foo');
}
function snapFitFunction2() {
console.log('Bar');
}
export snapFitFunction1;
export snapFitFunction2;
You may have to add exports for functions you want to use from the snapfit.js file.
You can call the external library in componentDidMount instead of React helmet like this:
const snapJs = (yourScriptPath) => {
const script = document.createElement("script");
script.src = yourScriptPath
script.async = true;
document.body.appendChild(script);
}
componentDidMount () {
snapJs("snapfit.js")
}
If you prefer using React Helmet then this would be the correct way:
import {Helmet} from "react-helmet";
const PuzzelSnapfit = props => (
<div>
<Helmet>
<script src="snapfit.js" type="text/javascript" />
</Helmet>
</div>
);
I have a website built in React Js and the same one on Next Js as well.
The problem which I am facing right now is, the router seems very slow in the nextJs compare to react-router-dom, It's taking almost 2-3 seconds to change the route.
Here are the URLs where you can feel the difference between the performance by moving around different pages.
https://cutt.ly/mhbPkOE (React Router Dom) vs
https://cutt.ly/BhbPvHv (NextJs)
I had read some comments on Github where few experts are saying that It will resolve in production. but It looks same in production too.
Please have a look at the following code
_app.jsx
// import App from 'next/app'
import React from "react"
import Router from 'next/router';
import "../static/sass/application.scss";
import "bootstrap/dist/css/bootstrap.min.css";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import 'semantic-ui-css/semantic.min.css'
import { wrapper } from "../../redux/utils/store"
import App from 'next/app';
// A simple component that we created
import {LoaderOverlay} from '../components/Reusable'
class MyApp extends App {
constructor(props){
super(props)
this.state = {
isLoading: false,
}
Router.onRouteChangeStart = (url) => {
// Some page has started loading
this.setState({
isLoading: true,
}) // set state to pass to loader prop
};
Router.onRouteChangeComplete = (url) => {
// Some page has finished loading
this.setState({
isLoading: false,
}) // set state to pass to loader prop
};
Router.onRouteChangeError = (err, url) => {
this.setState({isLoading: false,})
};
};
render() {
const {Component, pageProps} = this.props
return (
<div>
{this.state.isLoading ? (
<LoaderOverlay/>
) : (
<Component {...pageProps} />
)}
</div>
)
}
}
export default wrapper.withRedux(MyApp);
_document.jsx
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const originalRenderPage = ctx.renderPage
ctx.renderPage = () =>
originalRenderPage({
// useful for wrapping the whole react tree
enhanceApp: (App) => App,
// useful for wrapping in a per-page basis
enhanceComponent: (Component) => Component,
})
// Run the parent `getInitialProps`, it now includes the custom `renderPage`
const initialProps = await Document.getInitialProps(ctx)
return initialProps
}
render() {
return (
<Html lang="en">
<Head>
<link async rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui#2.4.1/dist/semantic.min.css"/>
</Head>
<body>
<div className={'main-wrapper'}>
<Main />
</div>
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
Development mode (next dev) is much slower because the routes aren't pre-built.
All delay related to routing assuming you don't have any server side blocking data requirements via getInitialProps, getServerSideProps, should not be present when running production mode with next build followed by next start.
Not sure if you have found a fix for this yet, but I came across this article about "shallow routing". I can't see much improvement in my application when using it, but maybe it will help someone else:
https://nextjs.org/docs/routing/shallow-routing
Hey I think you are in your production mode.
That's why it is slow. But if you will host your site it will be pretty much like react only.
But then also if you want to routing fast
Then npm i next#4.2.3 --save will work fine..
to solve this issue followed the commands:
yarn build/nmp build
yarn start/npm start
I hope this will solve this issue
I've got a nice little ES6 React component file (simplified for this explanation). It uses a library that is browser-specific, store This all works beautifully on the browser:
/app/components/HelloWorld.js:
import React, { Component } from 'react';
import store from 'store';
export default class HelloWorld extends Component {
componentDidMount() {
store.set('my-local-data', 'foo-bar-baz');
}
render() {
return (
<div className="hello-world">Hello World</div>
);
}
}
Now I'm trying to get it to render on the server as follows, using babel-register:
/server/routes/hello-world.js:
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import HelloWorld from '../../app/components/HelloWorld'
export default function(req, res) {
res.render('root', {
reactHTML: ReactDOMServer.renderToString(<HelloWorld />),
});
}
I get an error from the node server saying "window is not defined" due to importing 'store'. Ideally I could conditionally import by detecting the environment (node vs browser), but conditional imports aren't supported in ES6.
What's best way to get around this? I don't actually need to execute the browser code (in this case componentDidMount won't be called by ReactDOMServer.renderToString) just get it running from node.
One way would be using babel-rewire-plugin. You can add it to babel-register via the plugins option
require('babel/register')({
plugins: ['babel-rewire-plugin']
});
Then rewire your store dependency to a mocked store:
HelloWorld.__Rewire__('store', {
set: () => {} // no-op
});
You can now render HelloWorld from the server peacefully.
If you want to suppress the load of some npm module, you can just mock it.
Put this on your node.js application setup, before the HelloWorld.js import:
require.cache[require.resolve('store')] = {
exports: {
set() {} // no-op
}
};
This value will be used instead of the real module, which doesn't need on your purposes. Node.js module API is stable, so this behavior will not be broken and you can rely on it.