Good afternoon all,
I am trying to import some React components from another application of mine, into my new Electron app. On the new Electron app, I changed aspects of index.html, so that I can reference ‘root’ in my App.js component(which I imported from my react-app to the electron app). I also imported my index.js from my react app into my new electron app, and nested it in the src file.
The Problem:
I am currently getting back a blank screen, and am not sure why. It might be that i referenced some files incorrectly, or a routing issue, but I’m not certain.
(Picture of Screen Attached Below)
File Directory:
The Code:
App.js:
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import {
BrowserRouter as Router,
} from "react-router-dom";
import NavbarA from './src/components/NavbarA';
function App() {
return (
<div>
<Router>
<NavbarA/>
</Router>
</div>
);
}
export default App;
Main.js
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
Index.html
<!DOCTYPE html>
<html>
<div id="root"></div>
<title>Spotify</title>
<!-- You can also require other files to run in this process -->
<script src="./App.js>"></script>
</html>
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Package.json
{
"name": "electron-quick-start",
"version": "1.0.0",
"description": "A minimal Electron application",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"repository": "https://github.com/electron/electron-quick-start",
"keywords": [
"Electron",
"quick",
"start",
"tutorial",
"demo"
],
"author": "GitHub",
"license": "CC0-1.0",
"devDependencies": {
"electron": "^18.2.0"
},
"dependencies": {
"bootstrap": "^5.1.3",
"firebase": "^9.7.0",
"react": "^18.1.0",
"react-audio-player": "^0.17.0",
"react-bootstrap": "^2.3.1",
"react-is": "^18.1.0",
"react-router-dom": "^6.3.0",
"react-scripts": "^5.0.1"
}
}
Let Me Know What You Think!
Best,
-Zpo
Had a similar issue and including
import * as React from 'react';
in the component -- NavbarA in your case -- solved my issue.
Related
I'm developing this application with Next.js i'm using typescript as a language. I'm also using module css to style my components. I initialized my next application by running the following command:
yarn create next-app .
Then few days back the application was running fine but not smoothly though. I'm using window 10 [Windows [Version 10.0.19042.1165] and my node version is v14.17.5 I'm also using yarn v1.22.10. I always face this problem when my next application grows large when I run:
yarn run dev
I get this:
yarn run v1.22.10
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from ....
info - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
event - compiled successfully
event - build page: /
wait - compiling...
event - build page: /
but there's nothing that is displayed in the browser for more than 20 min the page will be loading and loading and loading. I'm thinking of changing to use gastby but i can't restart the whole process. If someone knows how to help me please help Here is my package.json file:
{
"name": "app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"#apollo/client": "^3.4.10",
"#material-ui/core": "^4.12.3",
"#material-ui/icons": "^4.11.2",
"#material-ui/lab": "^4.0.0-alpha.60",
"axios": "^0.21.1",
"firebase": "^9.0.0",
"graphql": "^15.5.2",
"next": "11.1.0",
"node-sass": "4.14.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-icons": "^4.2.0",
"react-redux": "^7.2.4",
"redux": "^4.1.1"
},
"devDependencies": {
"eslint": "7.32.0",
"eslint-config-next": "11.1.0",
"typescript": "^4.4.2"
}
}
Here is my index.tsx aka my home / code if it may make sense
import { NextPage } from "next";
import React from "react";
import styles from "../styles/Home.module.css";
import Header from "../components/minor/flesh/Header/Header";
import HeaderSkeleton from "../components/minor/skeletons/components/Header/HeaderSkeleton";
import Fleets from "../components/minor/flesh/Fleets/Fleets";
import FleetsSkeleton from "../components/minor/skeletons/components/Fleets/FleetsSkeleton";
import Form from "../components/minor/flesh/Form/Form";
import { IoIosCreate } from "react-icons/io";
import { IconButton } from "#material-ui/core";
import { ThemeType } from "../types/major";
import FormSkeleton from "../components/minor/skeletons/components/Form/FormSkeleton";
import { useQuery } from "#apollo/client";
import HELLO_WORLD_QUERY from "../graphql/queries/hello/hello";
import Post from "../components/minor/flesh/Post/Post";
import { useSelector } from "react-redux";
import PostSkeleton from "../components/minor/skeletons/components/Post/PostSkeleton";
import { apolloClient } from "../lib/apolloClient";
import USER_QUERY from "../graphql/queries/user/user";
import { useRouter } from "next/router";
interface Props {
data: any;
}
const Home: NextPage<Props> = ({ data }) => {
data = JSON.parse(data);
const router = useRouter();
const [showForm, setShowForm] = React.useState(false);
const theme = useSelector((state: any) => state.theme);
const className: string = `${styles.app} ${
theme === "dark" ? styles.dark__theme : styles.light__theme
}`;
return (
<div className={className}>
{/* <Header theme="light" /> */}
<HeaderSkeleton theme={theme} />
{/* <FormSkeleton theme={theme} /> */}
{showForm ? <Form theme={theme} setShowForm={setShowForm} /> : null}
<div className={styles.app__main}>
<Fleets theme={theme} />
<FleetsSkeleton theme={theme} />
<PostSkeleton theme={theme} />
<PostSkeleton theme={theme} />
<PostSkeleton theme={theme} />
<PostSkeleton theme={theme} />
<PostSkeleton theme={theme} />
<Post theme={theme} />
<Post theme={theme} />
<Post theme={theme} />
<Post theme={theme} />
</div>
<IconButton title="new post" onClick={() => setShowForm(true)}>
<IoIosCreate className={styles.home__create__post__icon} />
</IconButton>
</div>
);
};
Home.getInitialProps = async (context) => {
const user = await apolloClient.query({
query: USER_QUERY,
});
if (!user.data?.user) {
context.res.writeHead(307, { Location: "http://localhost:3000/welcome" });
return {
data: null,
};
}
return {
data: JSON.stringify(user, null, 2),
};
};
export default Home;
I am not sure, but it seems to work in my case. When I start server with different port (not the default 3000) it works just fine next dev -p 1234
Running it in an incognito window worked for me
Do a hard reload (Ctrl + Shift + R) if not running on port 3000.
I just had this same issue, localhost:3000 wasn't showing anything for about 15 minutes.
Please check if you made changes to your config file, "I hadn't". So I fixed it by going to next.cofig.js file and pressing Ctrl + Z, but changed nothing. This tricked Next.js to think there's a change in there.
Then I restarted the server and it displayed fine.
Just hit Ctrl + click on http://localhost:3000 from terminal.
You will get the below result to perform the above operation in the terminal after yearn dev or npm run dev.
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
event - compiled client and server successfully in 357 ms (154 modules)
Try to rewrite your _app.js file. It can help to resolve your problem.
I'm using next.js with TypeScript and Material UI.
You can use the following code and replace that.
// pages/_app.tsx
import * as React from 'react';
import Head from 'next/head';
import { AppProps } from 'next/app';
import { ThemeProvider } from '#mui/material/styles';
import CssBaseline from '#mui/material/CssBaseline';
import { CacheProvider, EmotionCache } from '#emotion/react';
import theme from '../src/theme';
import createEmotionCache from '../src/createEmotionCache';
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();
interface MyAppProps extends AppProps {
emotionCache?: EmotionCache;
}
export default function MyApp(props: MyAppProps) {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
return (
<CacheProvider value={emotionCache}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</CacheProvider>
);
}
when a user clicks on Sign in using Google, the user is to be taken to the Google OAuth flow for the sign-in procedure. But on clicking the browser just changes its url to localhost:3000/auth/google and nothing happens.
It works fine if I explicitly provide the complete href i.e
http://localhost:5000/auth/google
App component:
import './App.css';
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div className="App">
Sign in using google
</div>
);
}
}
export default App;
package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"proxy": {
"/auth/google": {
"target": "http://localhost:5000/"
}
},
delete your proxy on package.json and try this
create setupProxy.js on your src directory then npm install http-proxy-middleware
const { createProxyMiddleware } = require("http-proxy-middleware");
const proxy = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware(
"/auth/google",
// replace with your endpoint
{ target: "http://localhost:5000" } // replace with your target
)
);
};
I keep getting this error: error screenshot
Here is the code that im using to import my custom google fonts:
import React, { useState } from "react";
import Home from "./screens/home";
import { View } from "react-native";
import * as Font from "expo-font";
import { AppLoading } from "expo";
const getFonts = () =>
Font.loadAsync({
"poppins-regular": require("./assets/fonts/Poppins-Regular.ttf"),
"poppins-bold": require("./assets/fonts/Poppins-Bold.ttf"),
});
export default function App() {
const [fontsLoaded, setFontsLoaded] = useState(false);
if (fontsLoaded) {
return <Home />;
} else {
return (
<AppLoading startAsync={getFonts} onFinish={() => setFontsLoaded(true)} />
);
}
}
Here is my Json Package:
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "~40.0.0",
"expo-splash-screen": "^0.8.1",
"expo-status-bar": "~1.0.3",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
"react-native-web": "~0.13.12"
},
"devDependencies": {
"#babel/core": "~7.9.0"
},
"private": true
}
I can't seem to find the error or fix it. I did this with another project before and it worked. The getting the font info is exactly the same. The only thing i can think of is maybe my packages are outdated atm? but Im not sure which package to even update.
Can someone please help?
I can see from your package.json that you are at expo SDK 40 (latest release as of now)
AppLoading has been extracted from the expo package in SDK 40
If you want to use this component, you should run expo install expo-app-loading and import AppLoading from its own package: import AppLoading from 'expo-app-loading';. This is part of an ongoing effort to make the expo package as lightweight as possible.
Check the expo blog here.
Steps:
STEP 1: expo install expo-app-loading
STEP 2:
replace import { AppLoading } from "expo";
by import AppLoading from 'expo-app-loading';
STEP 3: Restart your expo dev server (expo start)
My problem was that the first time reloading the app (with expo), the fonts were not loading.
After deleting, rewriting and saving the fontFamily inside of my StyleSheet, the text was being styled with the right font, as the app updates automatically every time you save a file.
I just couldn't make it work at the first load.
I solved the issue by putting a return in front of the Font.loadAsync() function:
const fetchFonts = () => {
return Font.loadAsync({ // <- add return here
"open-sans": require("./assets/fonts/OpenSans-Regular.ttf"),
"open-sans-bold": require("./assets/fonts/OpenSans-Bold.ttf"),
});
};
Now the AppLoading's startAsync gets the promise correctly and the fonts are loaded right after loading the app, without errors
const [isDataLoaded, setIsDataLoaded] = useState(false);
if (!isDataLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => setIsDataLoaded(true)}
onError={(err) => console.log(err)}
/>
);
}
you have to add the return keyword infront of font.loadAsync
Just a heads up, as of today, using startAsync method is depracted in expo-app-loading, you can use useEffect instead and run your function as you would like and handle all the errors there,
useEffect(() => {
const getAsyncData = async () => {
// Do my async request
setIsReady(true);
}
getAsyncData ();
}, [])
Assuming you have something like const [isReady, setIsReady] = useState(false); in your code
for me the following steps result:
STEP 1: stop device
STEP 2: expo install expo-app-loading
STEP 3: add the next line: import AppLoading from 'expo-app-loading';
STEP 4:
if (!isDataLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => setIsDataLoaded(true)}
onError={(err) => console.log(err)}
/>
);
}
I'm attempting to test a React component with Jest/Enzyme while using Webpack.
I have a very simple test #
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
it('App', () => {
const app = shallow(<App />);
expect(1).toEqual(1);
});
The relative component it's picking up is :
import React, { Component } from 'react';
import { render } from 'react-dom';
// import './styles/normalize.css';
class App extends Component {
render() {
return (
<div>app</div>
);
}
}
render(<App />, document.getElementById('app'));
However, running jest causes a failure:
Invariant Violation: _registerComponent(...): Target container is not a DOM element.
With errors #
at Object.<anonymous> (src/App.js:14:48)
at Object.<anonymous> (src/App.test.js:4:38)
The test files references line 4, which is the import of <App />, that causes a fail. The stack trace says line 14 of App.js is the reason for the failure -- which is nothing more than the render call from react-dom, something I've never had a challenge with (the app renders properly from my Webpack setup).
For those interested (Webpack code):
module.exports = {
entry: './src/App',
output: {
filename: 'bundle.js',
path: './dist'
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
},
{
test: /\.css$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
},
{
test: /\.scss$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass'
}
]
}
}
And my package.json:
{
"name": "tic-tac-dux",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --devtool eval --progress --colors --inline --hot --content-base dist/",
"test": "jest"
},
"jest": {
"moduleNameMapper": {
"^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"^.+\\.(css|sass)$": "<rootDir>/__mocks__/styleMock.js"
}
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.17.0",
"babel-jest": "^16.0.0",
"babel-loader": "^6.2.5",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.16.0",
"babel-preset-react": "^6.16.0",
"css-loader": "^0.25.0",
"enzyme": "^2.4.1",
"jest": "^16.0.1",
"jest-cli": "^16.0.1",
"node-sass": "^3.10.1",
"react-addons-test-utils": "^15.3.2",
"react-dom": "^15.3.2",
"sass-loader": "^4.0.2",
"style-loader": "^0.13.1",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.16.2"
},
"dependencies": {
"react": "^15.3.2",
"react-dom": "^15.3.2"
}
}
Oh, and if anyone is going to say that the div element isn't being loaded before the script, here's my index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>App</title>
</head>
<body>
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
</html>
What could be the reason for this peculiar rendering problem? Something to do with a new Jest update to 15.0?
For anyone else that was combing through the internet like I've been - looking for a solution to this when testing with Jest - I will back up the answer by #biphobe by saying Jest will cause this error to occur when you export something inside the same file that is calling ReactDOM.render.
In my case, I was exporting an object within my index.js where I was also calling ReactDOM.render. I removed this export and voila!
App.jsx is supposed to export the App class and do nothing more, render should be called elsewhere.
If you remove the render call from the App.jsx error should disappear, it pops up because the test environment doesn't supply the DOM with an app id.
As I see, this error arises in many cases and requires different approaches to solve it. My scenario is not the same as the example above, I use redux & router, although I was struggling with the same error. What helped me to solve this problem is to change index.js from:
ReactDOM.render(
<Provider store={store}>
<AppRouter />
</Provider>,
document.getElementById("root")
);
registerServiceWorker();
to:
ReactDOM.render(
(<Provider store={store}>
<AppRouter/>
</Provider>),
document.getElementById('root') || document.createElement('div') // for testing purposes
);
registerServiceWorker();
I found a solution for this error to my use case: Using the same Redux store React is using outside of React.
In trying to export my React's Redux store from index.tsx to be used somewhere else outside of the React application, I was getting the same error while running Jest tests (which make use of Enzyme) in the App.tsx file.
The error
The initial code that didn't work when testing React looked like this.
// index.tsx
import * as React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { applyMiddleware, compose, createStore } from "redux";
import App from "./components/App";
import { rootReducer } from "./store/reducers";
import { initialState } from "./store/state";
const middlewares = [];
export const store = createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middlewares)),
);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root"),
);
The solution that worked for me
Separate the Redux store logic into a new file named store.ts, then create a default export (to be used by index.tsx, i.e., the React application) and a non-default export with export const store (to be used from non-React classes), as follows.
// store.ts
import { applyMiddleware, compose, createStore } from "redux";
import logger from "redux-logger";
import { rootReducer } from "./store/reducers";
import { initialState } from "./store/state";
const middlewares = [];
export const store = createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middlewares)),
);
export default store;
// updated index.tsx
import * as React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import App from "./components/App";
import store from "./store";
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root"),
);
Using the Redux store in non-React classes
// MyClass.ts
import { store } from "./store"; // store.ts
export default class MyClass {
handleClick() {
store.dispatch({ ...new SomeAction() });
}
}
The default export
A small note before you go. Here is how to use the default and the non-default exports.
default export store; is used with import store from "./store";
export const store = ... is used with import { store } from "./store";
Hope this helps!
https://nono.ma/says/solved-invariant-violation-target-container-is-not-a-dom-element
Make sure in your test file you have well imported the render component.
It should be imported from #testing-library/react not from react-dom:
import { render } from '#testing-library/react';
Well we cant stop the developers from exporting component from any file and test it in isolation even if it have a react-dom import or usage in it .I mean what's wrong in it . We are not trying to disturb the whole file and test out some pieces of it as long as that is a valid piece of code .
Jest does not have an issue with react-dom , however conceptually they are diff . Jest is supposedly a browserless virtual test environment . React-DOM is a library which does the stitching of virtual DOM to real DOM for react components .
So obvious enough we can/should not test it in a normal way . But that is not the discussion for now. we are fine as long as our exported components are testable .
So Lets mock it
I did the mock in the testSetup file configured with "setupFilesAfterEnv" in jest config .
jest.mock("react-dom", () => {
return ({
"render": jest.fn()
})
})
That is pretty much worked for me. My react and react-dom code now happily go together in one file , works in browser and in the testing environment as well .
I have not encountered any issues because of this . If there is any I will be looking into the comment section
This solution worked for me. Just render if the element is there:
const root = document.getElementById('root');
if (root) {
render(
<App />,
root,
);
}
I found out this error can also be thrown when working with Portals in your tests. If you want to skip the error you can either mock Portals or add the Portal container element in your render method:
render (
<div>
<TestedComponent />
<div id="portal" />
</div>
)
I am trying to write a unit test of React and React-bootstrap components using Mocha.
All of my javascript is written in ES6, and I am using babel to transpile to ES5.
The files I am using are below.
After running npm install, I run npm test. This fails with the following output:
$ npm test
> # test /Users/tda0106/test/npm
> mocha --compilers jsx:babel-register simple-test.jsx
A simple test
1) "before all" hook: render and locate element
0 passing (34ms)
1 failing
1) A simple test "before all" hook: render and locate element:
AssertionError: expected null to exist
at Context.<anonymous> (simple-test.jsx:21:9)
npm ERR! Test failed. See above for more details.
TestUtils.renderIntoDocument is returning null for no reason that I can see. The TestUtil docs indicate that window and document must be defined before importing React, which is the point of test-dom.jsx.
I am certain that test-dom.jsx is loaded before React, because before I added the line setting global.navigator, React was throwing an error deep in its code trying to access that variable.
Any idea what I need to do to make this work?
package.json
{
"dependencies": {
"react": "^15.0.1",
"react-bootstrap": "^0.28.5",
"react-dom": "^15.0.1"
},
"scripts": {
"test": "mocha --compilers jsx:babel-register simple-test.jsx"
},
"devDependencies": {
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babelify": "^7.2.0",
"chai": "^3.5.0",
"jsdom": "^8.4.0",
"mocha": "^2.4.5",
"react-addons-test-utils": "^15.0.1"
}
}
test-dom.jsx
// React needs the basic dom objects defined before it is imported.
// And babel moves the imports before the rest of the code.
// So the dom setup needs to be in its own file and imported.
import jsdom from 'jsdom';
const document = jsdom.jsdom("hello world");
const window = document.defaultView;
// A super simple DOM ready for React to render into
// Store this DOM and the window in global scope ready for React to access
global.document = document;
global.window = window;
global.navigator = {userAgent: 'None'};
export default { document: document, window: window };
simple-test.jsx
import TestDom from './test-dom.jsx';
import { expect } from 'chai';
import React from 'react';
import { Panel } from 'react-bootstrap';
import TestUtils from 'react-addons-test-utils';
const Map = () => (
<Panel>A map </Panel>
);
describe('A simple test', () => {
before('render and locate element', () => {
const renderedComponent = TestUtils.renderIntoDocument(
<Map />
);
expect(renderedComponent).to.exist; // This fails
});
it('test something', () => {
expect(1+1).is('true');
});
});
.babelrc
{
"presets": [
"es2015",
"react"
]
}