This seems to be a common question, I'm finding a lot of people asking it and the responses are all very different and seem to be a bit hit and miss. I've watched various video tutorials, read plenty of tutorials, and the documentation. But alas it seems React is moving faster than the writers can keep up with. Or I'm just misunderstanding.
I want to create each component in a separate file, where logical to do so. I have React working, but am unable to work out how to import and use additional files. I don't know if this is because Chrome will not load in files when not on a web server (local test dev), or if I'm just going about it all wrong.
Here is my HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Test One</title>
</head>
<body>
<div id="rootNode"></div>
<script src="dist/bundle.js"></script>
</body>
</html>
And here is my main.js:
var React = require('react');
var ReactDOM = require('react-dom');
var Square = require('../components/square.jsx').square;
ReactDOM.render(
<div>
<h1>Hello React!</h1>
<Square />
</div>,
document.getElementById('rootNode')
);
This works fine if I don't try to use Square also.
This is my square.jsx:
class Square extends React.Component{
render() {
return (
<p>Square</p>
)
}
}
module.exports = {
square: Square
};
Babel create the bundle.js fine, no errors. Chrome throws the error:
Uncaught SyntaxError: Block-scoped declarations (let, const, function,
class) not yet supported outside strict mode
I have tried the following also for square, along with many other things, all lost from the undo queue:
import React from 'react';
class Square extends React.Component{
render() {
return (
<p>Square</p>
)
}
}
export default Square;
All help appreciated. React seems to make sense aside from separating out the class files.
Thanks.
EDIT:
Also tried:
var {Component} = React;
class Square extends Component{
render() {
return (
<p>Square</p>
)
}
}
window.Square = Square;
And if it helps here is the Gulp file:
var vendors = [
'react'
];
gulp.task('vendors', function () {
var stream = browserify({
debug: false,
require: vendors
});
stream.bundle()
.pipe(source('./src/main.js'))
.pipe(gulp.dest('./dist/bundle.js'));
return stream;
});
And the package.json:
{
"name": "reacttestone",
"version": "1.0.0",
"description": "Testing React Components",
"main": "index.js",
"dependencies": {
"babel-preset-react": "^6.1.2",
"babelify": "^7.2.0",
"react": "^0.14.2",
"react-dom": "^0.14.2"
},
"devDependencies": {
"gulp": "^3.9.0",
"vinyl-source-stream": "^1.1.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Myself",
"license": "MIT"
}
Your es6 example of exporting like export default Square should work fine. It looks like you've installed babelify but you're not using it in the transform process, hence why the browser is complaining that you're trying to use es6 features outside of strict mode.
If you look at the babelify instructions it says to do something like:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var gutil = require('gulp-util');
gulp.task('browserify', function () {
browserify('./src/main.js', { debug: true })
.transform('babelify', {presets: ['es2015', 'react']})
.bundle()
.on('error', gutil.log)
.pipe(source('bundle.js'))
.pipe(gulp.dest('./dist'))
});
gulp.task('watch',function() {
gulp.watch('./src/**/*.js', ['browserify'])
});
It looks like you only have babel-preset-react installed, you'll need to do npm i babel-preset-es2015 --save-dev. Also babelify and babel-preset-react are fine as devDependencies.
Related
I would like to create and use stylus variables globally in my Vue Vite project. How can I import stylus variables globally to use within the script section of my SFC?
Here's my Vite config:
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'#': path.resolve(__dirname, './src'),
},
},
css: {
preprocessorOptions: {
styl: {
additionalData: `#import "#/styles/styles.styl"`
}
}
}
})
In my styles.styl file I define a variable like:
contentSideMargin = 50px
In my SFC I try to use a style from styles.styl such as
<style lang="stylus" scoped>
#main-container
padding: $contentSideMargin /* have also tried `contentSideMargin` */
</style>
but it does not work.
—
EDIT: adding package.json. There are no visible errors, the variable is passed directly into the css rather than its value.
{
"name": "project",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"pinia": "^2.0.17",
"pug": "^3.0.2",
"vue": "^3.2.37",
"vue-router": "^4.1.3"
},
"devDependencies": {
"#vitejs/plugin-vue": "^3.0.0",
"stylus": "^0.58.1",
"stylus-loader": "^7.0.0",
"vite": "^3.0.0"
}
}
METHOD A) - CONFIGURING VITE FOR STYLUS USING additionalData PROPERTY
This is the solution You have been searching for
vite.config.js:
import { defineConfig } from 'vite'
import path from 'path'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
stylus: {
additionalData: `#import "${path.resolve(__dirname, 'src/assets/global_variables.styl')}"`
}
}
},
})
METHOD B) - IMPORTING STYLUS VARIABLES IN CSS
If you don't want to custom-configure how Vite should bundle your code, all your <style lang="stylus" scoped> must contain definitions of stylus variables that you are going to use in the component.
Either u can define the variables explicitly at the beginning of <style lang="stylus" scoped> or if you have variables definitions in a separate file, you can import that file:
App.vue:
<template>
<div id="my-div">THIS IS MY DIV</div>
</template>
<style lang="stylus" scoped>
#import "./assets/global.styl";
#my-div {
padding: 1rem;
color: $c-text;
background-color: $c-bg;
}
</style>
assets/global.styl:
$c-bg = red
$c-text = yellow
METHOD C) - CONFIGURING VITE WITH CUSTOM PLUGIN FOR STYLUS:
If you prefer not to use import within your components' <style> tags, you can configure Vite to automatically inject stylus files into the CSS of your app by including a custom Vite plugin vite-stylus-import-plugin.js. An advantage of this method over method A is that you can extra-customize the transformation of your stylus files.
vite-stylus-import-plugin.js:
import path from 'path'
export function importStylus() {
return {
name: 'vite-stylus-import-plugin',
async transform(code, id) {
if (/.stylus$/g.test(id)) {
return {
code: `
#import "${path.resolve(__dirname, 'src/assets/global_variables.styl')}"
${code}
`,
map: null,
}
}
return null
}
}
}
After that you can use that plugin in your Vite config file:
vite.config.js:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import { importStylus } from './vite-stylus-import-plugin.js'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), {
...importStylus(),
enforce: 'pre',
}]
})
WORKING DEMOS
I have a working demo for the last two methods HERE - GitHub repo HERE. In the demo, the big red <div> element was styled using the method B, the blue <div> was styled using the method C. The method A is not in my demo, but it works too
I think that instead
contentSideMargin = 50px
...
<style lang="stylus" scoped>
#main-container
padding: $contentSideMargin /* have also tried `contentSideMargin` */
</style>
The code should be
$contentSideMargin = 50px
...
<style lang="stylus" scoped>
#main-container {
padding: $contentSideMargin;
}
</style>
Thanks to #DVN-Anakin comment and the link provided in the comment ( github.com/TOA-Anakin/Vite-Vue3-TS-template) to a working boilerplate - it's easy to spot the differences
In short: dear stackoverflow users - please read the comments! Members here put their best effort to try to assist without making to much noise (hence comments). If you skip them or not reading them properly - you may loose some vital information that will help you to solve your problem (which is kinda of what we are doing here in the first place)
Hi I am new to React/JS and Electron and would like to write a desktop application using these technologies.
The problem I am facing now is that I am not sure how to call react component code from renderer.js. I have such coding structure.
electron-tutorial
src/
components/Test.js
application.js
electron-starter.js
mainWindow.html
package.json
And this is a list of code snippet of each file.
package.json:
"main": "src/electron-starter.js",
electron-starter.js
const application = require("./application");
global.application = new application();
global.application.run();
application.js
odule.exports = class Application {
createWindow() {
this.mainWindow = new BrowserWindow({
width: 1366,
height: 768,
...
pathname: path.join(__dirname, "./mainWindow.html"),
mainWindow.html
<body>
<div id="test"></div>
<script src="./renderer.js"></script>
</body>
So from mainWindow.html I want to call renderer.js. I learned that I know I can call functions in such way:
renderer.js
"use strict";
const { shell } = require("electron");
function hoge() {
console.log("hoge");
}
window.hoge();
But what I want to do is to call the react component below from renderer.js.
Test.js
import React from "react";
export class Test extends React.Component {
render() {
return <h1>Hello from Test class</h1>;
}
}
Could you please help me ? Thanks for reading !
As you are just starting out, I would recommend that you use a boilerplate like Electron-React.
I have a GatsbyJS project and I am trying to use a Hook, however I am getting this error.
First thing I did was delete the node_modules folder and the package.json.lock file and did npm install again, did not work.
Looking at the React documentation:-
You might have mismatching versions of React and React DOM.
As far as I know I do not have mismatching versions.
You might be breaking the Rules of Hooks. - As far as I am aware I am using a component
You might have more than one copy of React in the same app.
I tried as the React documentation suggests:-
// Add this in node_modules/react-dom/index.js
window.React1 = require('react');
// Add this in your component file
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);
This returns false for me so I might have two React however I cannot understand how.
This is my package.json file
{
"name": "gatsby-starter-hello-world",
"private": true,
"description": "A simplified bare-bones starter for Gatsby",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"dependencies": {
"gatsby": "^2.21.0",
"gatsby-image": "^2.4.0",
"gatsby-plugin-prefetch-google-fonts": "^1.4.3",
"gatsby-plugin-react-helmet": "^3.3.1",
"gatsby-plugin-sharp": "^2.6.0",
"gatsby-plugin-sitemap": "^2.4.2",
"gatsby-source-filesystem": "^2.3.0",
"gatsby-source-strapi": "0.0.12",
"gatsby-transformer-sharp": "^2.5.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-helmet": "^6.0.0",
"react-icons": "^3.10.0",
"react-markdown": "^4.3.1"
},
"devDependencies": {
"prettier": "2.0.5"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-hello-world"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}
My component looks like this (just want to verify that the useState works):-
import React, {useState} from "react"
import { graphql, useStaticQuery } from "gatsby"
const query = graphql`
{
allStrapiExperiences(sort: {fields: sequence, order: DESC}) {
nodes {
company
job_title
short_desc
website
address
desc {
id
name
}
job_date
sequence
snapshot {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`
const Experiences = () => {
const data = useStaticQuery(query);
const { allStrapiExperiences: {nodes : experiences} } = data;
const [value, setValue] = useState(0)
// const { company, jobt_title, short_desc, website, address, desc, job_date, sequence, snapshot } = experiences[value]
return (
<div>Some details go here</div>
)
}
export default Experiences
And I am calling this component in the experience.js page:-
import React from "react"
import Experiences from "../components/Experiences/Experiences"
import Layout from "../components/Generic/Layout"
export default () => {
return (
<Layout>
<Experiences />
</Layout>
)
}
I have looked at some posts online, and did some troubleshooting but so far I cannot understand why I am having this problem.
Any ideas why I might be getting this error?
Thanks for your help and time
UPDATE
Just a small update on this, I could not solve the issue, so i took the unwanted route but I thing the best one at the moment to start with the basic blog starter project and start building up from that. Infact, the hooks do work in this project, so I guess I have some mess with dependencies but I cannot figure out what is wrong.
This might seem weird, but can you move your query definition into the call to useStaticQuery? Gatsby uses static analysis to extract these and historically there have been some issues defining a query and assigning it to a variable in this way. For example:
const Experiences = () => {
const data = useStaticQuery(graphql`
{
allStrapiExperiences(sort: {fields: sequence, order: DESC}) {
...
}
}
`);
}
To ensure you don't have multiple versions of React being used, you can try this:
exports.onCreateWebpackConfig = ({ stage, actions }) => {
actions.setWebpackConfig({
resolve: {
// Ensure all dependencies use the same instance of React
alias: { react: path.resolve("./node_modules/react") },
},
})
}
This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 4 years ago.
I'm building a React app and attempting to update some JavaScript functions to use ES6 destructured arrow syntax.
Index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
function TestMe() {
const name = "User";
const message = "Welcome!";
return (
<div>
<Hello name={name} />
<Message message={message} />
</div>
);
}
ReactDOM.render(<TestMe/>, document.querySelector('#root'));
const Hello = ({ name }) => (
<span>Hello, {name}</span>
);
function Message(props) {
return (
<div className="message">
{props.message}
</div>
);
}
The Message function will render, but the Hello function throws the following error in the browser (after successful build):
"""
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of TestMe. """
Here's my package.json, just in case:
{
"name": "jsx-exercises",
"version": "0.1.0",
"private": true,
"dependencies": {
"eslint": "^5.6.0",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-scripts": "2.1.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
Why am I getting this error?
Declarations in Javascript get "hoisted", which means that they can be accessed in the whole scope, even before they are declared. If you use a function declaration also the initialization happens when the scope starts:
{ // scope begins
a();
function a() { }
} // scope ends
Now variables can only be accessed after they were initialized:
setTimeout(() => console.log(a)); // 1
console.log(a); // undefined
var a = 1;
In your case you access Hello before it was initialized.
Fun fact: Accessing variables declared with let or const before the initialization happened throws a SyntaxError (for a good reason, q.e.d.) so one can see that your building pipeline replaced const with var to support older browsers.
You must move Hello on the top of your file, because TestMe can't see this const. Functions javascript can see anyway, because it's function declaration
We're trying to integrate a new React Native app to an existing native Android app. Following the RN official docs we managed to get it working but with some issues regarding the navigation.
We've native and non-native (JS) screens, and we need a good way to navigate between all screens regardless if a screen is native or not.
We tried to adopt native-navigation and react-native-navigation to see if any address our issue but none of them actually worked.
Currently, we have registered all our RN screens like this:
const provide = (store, Screen) => {
return props => (
<Provider store={store}>
<Screen {...props} />
</Provider>
);
};
const store = configureStore();
AppRegistry.registerComponent('Home', () => provide(store, HomeComponent));
We also created a Native Module we call "Navigator" that has navigation method called openComponent that accepts screen name and its props. Here is how the implementation of openComponent looks:
// our native module code ...
#ReactMethod
public void openComponent(String name, String extra) {
try {
Intent intent = new Intent(this.getReactApplicationContext(), MyReactActivity.class);
intent.putExtra("moduleName", name);
intent.putExtra("extra", extra);
getCurrentActivity().startActivityForResult(intent, 0);
}
catch (Exception e) {
e.printStackTrace();
Crashlytics.logException(e.getCause());
}
}
Then whenever we want to navigate on the RN side we simply call our custom navigator with the target screen props.
The problem with the current approach is that the RN part is being restarted whenever we navigate to RN-based screens which causes the Redux store to be empty.
Here how our "onCreate" method looks like for our ReactActivity.java class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle initialProperties = new Bundle();
initialProperties.putString("loginToken", HJSession.getSession().getSessionId());
initialProperties.putString("username", HJSession.getSession().getUserName());
initialProperties.putString("userId", HJSession.getSession().getUserId().toString());
String moduleName = "topics";
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
moduleName = bundle.getString("moduleName");
try {
String extra = bundle.getString("extra");
initialProperties.putString("extra", extra);
}
catch (Exception e) {
e.printStackTrace();
Crashlytics.logException(e.getCause());
}
}
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setJSMainModulePath("index")
.addPackages(Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(),
new RNFirebaseMessagingPackage(),
new RNFirebaseNotificationsPackage(),
new RNI18nPackage(),
new VectorIconsPackage(),
new HJRNPackages(),
new NativeNavigationPackage()
))
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, moduleName, initialProperties);
setContentView(mReactRootView);
}
Actually, for your question case, you should upload a little tiny scale of your project that has this issue on Gitlab or Github and put its link here, Hence we could help better.
Indeed, I'm a JavaScript, React, React Native developer and I cannot help anybody in the native side, But definitely, I believe you and your colleagues choose the wrong way for your application.
React Native is an unstable JavaScript project that has unstable native codes that are changing in time, so you should write all of your features just by using JavaScript. Just like Sophie Albert said in this article, They wanna make a big break change to React Native, So, It is better all of the codes to be written in JavaScript not native (Java, Objective C).
At first, I believe your choosing on react-native-navigation was wrong. Why you do not use react-navigation?
Because 99.7% of react-navigation based on JavaScript and changing native sides by Facebook teams, do not affect your project and development and debugging is very easy. absolutely, you can use every trend library like Redux, because of your project based on JavaScript.
My colleagues and I are developing a large scale React Native application for Sheypoor, except the splash screen all of the app based on JavaScript and in our inputs tests we didn't get even one crash or error or unwanted restart.
If it is possible for you, roll back your navigation to a full JavaScript navigation library like react-navigation which we chose. If you uploaded a reproduction repository I could help you better than this situation. but I put some of our code structure to help you for roll back to react-navigation:
The index.js of our project:
import { AppRegistry } from 'react-native';
import App from './app/App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
The root file of our app, the App.js file:
import React from 'react';
import { Provider } from 'react-redux';
import RootNavigation from './RootNavigation';
import { onNavigationStateChange } from './utils/routes';
import configureStore from './redux/configureStore';
const store = configureStore();
const App = () => (
<Provider store={store}>
<RootNavigation onNavigationStateChange={onNavigationStateChange} />
</Provider>
);
export default App;
The RootNavigation.js file, but it is for our earlier commits not now. I don't put the newer version because of its complexities:
import { createSwitchNavigator } from 'react-navigation';
import { Loading, Dashboard, SignInStack, ListingManagement } from './screens';
const RootNavigation = createSwitchNavigator(
{
Loading,
SignInStack,
Dashboard,
ListingManagement
},
{
initialRouteName: 'SignInStack'
}
);
export default RootNavigation;
And at last, the earlier version of package.json:
{
"name": "sheypoor",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"android": "npx react-native run-android",
"ios": "npx react-native run-ios",
"physical-android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
"test": "jest",
"eslint": "eslint .",
"clean": "react-native-clean-project",
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": [
"eslint --fix ."
]
},
"dependencies": {
"formik": "^1.3.0",
"lint-staged": "^7.3.0",
"prop-types": "^15.6.2",
"react": "16.5.0",
"react-native": "0.57.1",
"react-native-confirmation-code-field": "^1.2.2",
"react-native-vector-icons": "^5.0.0",
"react-navigation": "^2.16.0",
"react-redux": "^5.0.7",
"redux": "^4.0.0",
"yup": "^0.26.6"
},
"devDependencies": {
"babel-eslint": "^9.0.0",
"babel-jest": "23.6.0",
"babel-plugin-module-resolver": "^3.1.1",
"babel-plugin-root-import": "^6.1.0",
"eslint": "^5.5.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^3.0.1",
"eslint-import-resolver-babel-plugin-root-import": "^1.1.1",
"eslint-plugin-flowtype": "^2.50.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-prettier": "^2.6.2",
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-react-native": "^3.3.0",
"eslint-plugin-sort-imports-es6-autofix": "^0.3.0",
"flow-bin": "^0.78.0",
"jest": "23.6.0",
"metro-react-native-babel-preset": "0.45.6",
"prettier": "^1.14.3",
"react-native-clean-project": "^3.0.0",
"react-native-config": "^0.11.5",
"react-test-renderer": "16.5.0",
"redux-devtools-extension": "^2.13.5"
},
"jest": {
"preset": "react-native"
},
"rnpm": {
"assets": [
"./app/assets/fonts"
]
}
}
With these codes and configurations, we didn't give even one error.
In the ReactActivity.java one can check for Bundle savedInstanceState
... in order to control when the React application is being instanced:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* it's always NULL on first run */
if (savedInstanceState == null) {
Bundle initialProperties = new Bundle();
initialProperties.putString("loginToken", HJSession.getSession().getSessionId());
initialProperties.putString("username", HJSession.getSession().getUserName());
initialProperties.putString("userId", HJSession.getSession().getUserId().toString());
String moduleName = "topics";
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
moduleName = bundle.getString("moduleName");
try {
String extra = bundle.getString("extra");
initialProperties.putString("extra", extra);
} catch (Exception e) {
Crashlytics.logException(e.getMessage());
Log.e("ReactActivity", e.getMessage());
}
}
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setJSMainModulePath("index")
.addPackages(Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(),
new RNFirebaseMessagingPackage(),
new RNFirebaseNotificationsPackage(),
new RNI18nPackage(),
new VectorIconsPackage(),
new HJRNPackages(),
new NativeNavigationPackage()
))
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, moduleName, initialProperties);
setContentView(mReactRootView);
}
}