React hooks widget works when used directly but not when imported from NPM - npm

I have a moderately simple example of a React Hooks widget whose function it is to provide context hooks to provide state that can set a few strings and switch the current Material UI theme. Here is the working demo. By clicking on the button labeled "NEXT THEME" you can see the page toggle between yellow and blue, along with some text changes indicating the name of the theme.
Its a contrived example, but the idea is that at the top of my site, I'm wrapping all content with context providers so that any nested widget can access shared state. Looks like this:
import React from "react";
import { AppContext } from "./AppContext";
import { ThemeContextProvider } from "./ThemeContext";
export default function App(props) {
return (
<div>
<ThemeContextProvider>
<AppContext>{props.children}</AppContext>
</ThemeContextProvider>
</div>
);
}
Everything is working as I said in the demo I've linked above. But when I publish this code to NPM and then use it in another project, it mostly works except for one import piece--the theme color will not change. All other state changes work right--all of the other state changes are textual and there are no problems, but the color will not change.
The theme is provided by Material UI, and I suspect that there is an issue with the way that I am rolling all this code up for publishing to NPM. I am using Rollup--here is rollup.config.js:
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import resolve from 'rollup-plugin-node-resolve';
import json from '#rollup/plugin-json';
const {terser} = require('rollup-plugin-terser');
import pkg from './package.json';
export default {
input: 'src/index.js',
output: [
{
file: pkg.main,
format: 'cjs',
sourcemap: true
},
{
file: pkg.module,
format: 'es',
sourcemap: true
}
],
plugins: [
external(),
// url({ exclude: ['**/*.svg'] }),
babel({
exclude: 'node_modules/**',
runtimeHelpers: true
}),
resolve({
preferBuiltins: true,
browser: true
}),
commonjs({
include: 'node_modules/**',
browser: true,
namedExports: {
'node_modules/react/index.js': [
'createContext',
'useContext',
'useEffect',
'useState'
],
'node_modules/react-is/index.js': [
'ForwardRef',
'Memo'
],
'node_modules/prop-types/index.js': [
'elementType'
]
}
}),
terser(),
json()
]
};
And here is my package.json:
{
"name": "#data-factory/theme-context-test",
"version": "0.0.1",
"description": "Code from CodeSandbox",
"author": "sellis42",
"main": "dist/index.js",
"module": "dist/index.es.js",
"jsnext:main": "dist/index.es.js",
"engines": {
"node": ">=8",
"npm": ">=5"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "rollup -c",
"start": "rollup -c -w",
"prepare": "npm run build",
"predeploy": "cd example && npm install && npm run build"
},
"peerDependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0"
},
"devDependencies": {
"#babel/core": "^7.9.0",
"#babel/plugin-transform-runtime": "^7.9.0",
"#babel/preset-env": "^7.9.0",
"#babel/preset-react": "^7.0.0",
"#babel/runtime": "^7.9.2",
"#material-ui/core": "^4.9.8",
"#material-ui/icons": "^4.9.1",
"#material-ui/styles": "^4.9.6",
"#rollup/plugin-json": "^4.0.2",
"cross-env": "^5.2.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "^3.4.0",
"rollup": "^1.32.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^9.3.4",
"rollup-plugin-node-resolve": "^4.2.4",
"rollup-plugin-peer-deps-external": "^2.2.2",
"rollup-plugin-terser": "^4.0.4",
"typeface-roboto": "0.0.75"
}
}
I feel as if there is something missing from my rollup configuration. This project is on my local development system and is slightly different that the linked code. I essentially have all the code that I publish in the root of the widget module, and an example folder that demonstrates how to use the widget. I use npm link so that the example widget can use it, and that is where I see the issue I'm trying to resolve. I can copy the entire root widget to a subfolder of the example src and import it from there instead of from NPM and it works again.
Any help or ideas would be appreciated. I can put all of my code to Git if anyone is interested in taking a deeper look.

I've sidestepped the issue altogether by not using a ThemeProvider in the ThemeContext. Here is what is returned by the ThemeContext hook (source abbreviated):
return (
<ThemeContext.Provider value={{theme, setTheme ... }}>
<ThemeProvider theme={theme}>{props.children}</ThemeProvider>
</ThemeContext.Provider>
);
I changed this to:
return (
<ThemeContext.Provider value={{theme, setTheme ... }}>
{props.children}
</ThemeContext.Provider>
);
It is the responsibility of children then to supply a ThemeProvider. As long as I avoid providing the ThemeProvider in my hooks I seem to be ok.
I'm not sure why this is, but I can live with it.

Related

npm run dev mix doesn't work in laravel 9

I have a fresh laravel 9 project
I want to create an auth system with laravel command by using
composer require laravel/ui
and also
php artisan ui bootstrap --auth
after that I did
npm install
npm run dev
but rather that opening a mix development to generate css styles of auth pages it gave me this output in terminal
npm run dev image
and the page style is being like this
Page styles
I found the solution for this problem
the problem was in the package.json file
package.json was like this:
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"#popperjs/core": "^2.10.2",
"axios": "^0.25",
"bootstrap": "^5.1.3",
"laravel-mix": "^6.0.49",
"laravel-vite-plugin": "^0.4.0",
"lodash": "^4.17.19",
"postcss": "^8.1.14",
"sass": "^1.32.11",
"sass-loader": "^11.0.1",
"vite": "^2.9.11"
}
}
As you can see the dev in script was applied to vite,
"scripts": {
"dev": "vite",
"build": "vite build"
}
I just modified vite to mix and run
npm install again
and the problem was resolve and tyles of my login page generated successfully
Styles result
Update - ## Better Solution:
Installing Laravel/ui
composer require laravel/ui
Install Bootstrap Auth Scaffold
php artisan ui bootstrap --auth
In Vite.config file
import path by adding this at top:
import path from 'path';
after plugins add this:
resole: {
alias: {
'~bootstrap': path.resolve(__dirname, 'node_module/bootstrap'),
}
}
final result of vite config file will be like this:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import path from 'path';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/sass/app.scss',
'resources/js/app.js',
],
refresh: true,
}),
],
resole: {
alias: {
'~bootstrap': path.resolve(__dirname, 'node_module/bootstrap'),
}
}
});
From resources/js/app.js - add these lines
import '../sass/app.scss';
import * as boostrap from 'bootstrap'
Final Result of resources/js/app.js will be like this
import './bootstrap';
import '../sass/app.scss';
import * as boostrap from 'bootstrap'
Final Step is to change styles and script to #vite directive in resources/view/layouts/app.blade.php
change any css or js files from this type
<link href="{{asset('css/app.css')}}" rel="stylesheet" />
to #vite directive type
#vite(['resources/css/app.css', 'resources/css/app.css'])
Make sure you already have those files before trying to include it, otherwise vite will cause an error.

Vue CLI 5 with Vuetify SCSS variables and CSS imports

I work for an organization that try to migrate a project from Vue CLI 4 to Vue CLI 5.
The project uses Vuetify and we have SCSS files that are used in the styles/variables.scss file (required by Vuetify to customize style) and also used in Vue components files via #import (SCSS variables sometimes need to be in the <script> section).
Here some example that show how SCSS variables are used through the app:
// styles/variables.scss
#import "colors.scss";
$some-vuetify-sass-variable: $color // from (colors.scss)
// plugins/vuetify.js
import { primaryColor } from "#/style/colors.scss";
Vue.use(Vuetify);
const options = {
theme: {
dark: false,
themes: {
light: {
primary: primaryColor,
// ...
},
},
},
};
export default new Vuetify(options);
// Component.vue
<template>
<v-chip
:color="clearPrimaryColor"
text-color="primary"
/>
</template>
<script>
import { clearPrimaryColor } from "#/style/colors.scss";
export default {
name: "Component",
created() {
this.clearPrimaryColor = clearPrimaryColor;
}
}
</script>
<style lang="scss">
.some-class {
background-color: $clearPrimaryColor
}
</style>
During the Vue CLI migration, we also tried to upgrade some Vuetify dependencies (sass and vuetify-loader). Upgrading sass from 8 to 10 version triggers a compile sass error.
With this reproduction branch: https://github.com/KevinFabre/vue-cli-5-vuetify-scss-variables-in-js (sass 8.0.0), the project does compile.
And for this one: https://github.com/KevinFabre/vue-cli-5-vuetify-scss-variables-in -js/tree/error/sass-error (sass 10.0.0), it does not compile:
ERROR Failed to compile with 2 errors
error in ./src/styles/app.module.scss
Syntax Error: SassError: This file is already being loaded.
╷
2 │ #import "app.module.scss";
│ ^^^^^^^^^^^^^^^^^
╵
src/styles/variables.scss 2:9 #import
src/styles/app.module.scss 1:9 root stylesheet
Is there extra Vue CLI 5 configuration to allow CSS import in JS while using Vuetify sass override ?
We've submitted issues to vuetify-loader and Vue CLI but didn't receive any reply for now:
https://github.com/vuetifyjs/vuetify-loader/issues/234
https://github.com/vuejs/vue-cli/issues/7083
{
"devDependencies": {
"#babel/preset-env": "^7.11.0",
"#cypress/webpack-preprocessor": "^5.4.1",
"#mdi/font": "^6.5.95",
"#vue/cli-plugin-babel": "^4.4.5",
"#vue/cli-plugin-e2e-cypress": "^4.4.5",
"#vue/cli-plugin-eslint": "^4.4.5",
"#vue/cli-service": "^4.4.5",
"#vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.0.1",
"core-js": "^3.6.5",
"eslint": "^7.3.1",
"eslint-plugin-mocha": "^9.0.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-unused-imports": "^1.1.5",
"eslint-plugin-vue": "^7.0.0",
"eslint-plugin-vuetify": "^1.1.0",
"lint-staged": "^10.2.11",
"sass": "~1.32.0",
"sass-loader": "^10.0.0",
"style-resources-loader": "^1.2.1",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue-cli-plugin-style-resources-loader": "^0.1.3",
"vue-cli-plugin-vuetify": "^2.0.6",
"vue-svg-loader": "^0.16.0",
"vue-template-compiler": "^2.6.12",
"vuetify-loader": "^1.7.3",
}
}
Thank you for your time.
Components must avoid importing files that are already imported in the global variables stylesheet (src/styles/variables.scss). This was the case with app.module.scss (loaded in src/styles/variables.scss and in src/components/HelloWorld.vue), causing the error about the file being loaded twice.
One solution is to move the color definitions from app.module.scss into its own file, and import that in variables.scss instead of app.module.scss. Then, components could import app.mdoule.scss without running into the original problem.
/* src/styles/app.module.scss *
:export {
whitecolor: $white-color;
darkcolor: $dark-color;
lightcolor: $light-color;
mediumcolor: $medium-color;
alertcolor: $alert-color;
lightblackcolor: $light-black-color;
blackcolor: $black-color;
}
/* src/styles/colors.scss */
$white-color: #fcf5ed;
$dark-color: #402f2b;
$light-color: #e6d5c3;
$medium-color: #977978;
$alert-color: #cb492a;
$light-black-color: #706e72;
$black-color: #414042;
/* src/styles/variables.scss */
#import "~vuetify/src/styles/settings/_colors.scss";
#import "colors.scss";
$material-light: (
background: map-get($grey, "lighten-1")
);
demo
This basically pertains to duplicate parsing of the import files, declared in your vuejs app.
There are 2 ways to solve it:
Use #use instead of #import where you are getting the Sass import error. Like, #import "app.module.scss"; becomes #use "app.module.scss";
Other alternative is to downgrade the sass-loader library to "^8.0.2"
Let me know if the above solutions work for you, meanwhile i will update my answer if i find any new solution.

Vue 3 Web Components do not build and instead throw error

I created a new vue project with the vue cli and then adjusted main.js to support web-components:
import Vue from 'vue';
import wrap from '#vue/web-component-wrapper';
import HelloWorld from "./components/HelloWorld";
const CustomElement = wrap(Vue, HelloWorld);
window.customElements.define('my-custom-element', CustomElement);
When running vue-cli-service build --target wc I get the following error:
ERROR Vue 3 support of the web component target is still under development.
I can not figure out why this error occurs and what i can do to fix it.
package.json:
...
"dependencies": {
"#vue/web-component-wrapper": "^1.2.0",
"core-js": "^3.6.5",
"vue": "^3.0.2"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-service": "^4.5.4",
"#vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0"
},
...
I use #vue/cli version 4.5.9.
Hello there is a update in this. Topic see
issue on github and comment on twitter looks like with vue 3.2.0 we have this feature back i created a small stackblitz but as you can see styles are not applied
Vue-CLI does not currently support web components for Vue 3, but you can do it by hand. This worked for me.
src/MyLib.js
export { default as TheFoo } from '#/components/TheFoo.vue';
export { default as TheBar } from '#/components/TheBar.vue';
src/MyLib-WC.js
import { defineCustomElement } from 'vue';
import TheFoo from '#/components/TheFoo.vue';
import TheBar from '#/components/TheBar.vue';
const TheFooWC = defineCustomElement(TheFoo);
const TheBarWC = defineCustomElement(TheBar);
export {
TheFooWC,
TheBarWC
};
export function register () {
customElements.define('the-foo', TheFooWC);
customElements.define('the-bar', TheBarWC);
}
package.json
{
"scripts": {
"build": "npm run build-lib && npm run build-wc",
"build-lib": "vue-cli-service build --name=MyLib --modern --dest=dist/lib --target=lib src/MyLib.js",
"build-wc": "vue-cli-service build --name=MyLib --modern --dest=dist/wc --target=lib --inline-vue src/MyLib-WC.js"
}
}
Then npm run build.
As #tony19 pointed out the solution is to not use Vue3, as it cureently does not support web components.
The problem for me was the misleading error message, as "still under developement" did not signal to me, that web components were completly unsupported. I understood it, as a "not everything will work perfectly".

How to fix Expo Print.printToFileAsync(options) undefined is not an object error

I am trying to use Expo's Print.printToFileAsync(options but I keep on getting [Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_expoPrint.Print.printToFileAsync')].
I looked for a lot of solutions online but couldn't find a solution to this. I started using React Native libraries but as I searched, turns out I can only use Expo's library so I switched to Print.printToFileAsync().
App.js
import React, {Component} from 'react';
import { StyleSheet, Text, View, TouchableHighlight } from 'react-native';
import { Print } from 'expo-print';
export default class App extends Component {
async createPDF() {
let filePath = await Print.printToFileAsync({
html: "<h1>PDF TEST</h1>",
width : 612,
height : 792,
base64 : false
});
alert('PDF Generated', filePath.uri);
}
render() {
return(
<View>
<TouchableHighlight onPress={this.createPDF} style={styles.Main}>
<Text>Create PDF</Text>
</TouchableHighlight>
</View>
)
}
}
const styles = StyleSheet.create({
Main : { marginTop : 100 }
});
Package.JSON
{
"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": "^33.0.0",
"expo-print": "^5.0.1",
"react": "16.8.3",
"react-dom": "^16.8.6",
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
"react-native-html-to-pdf": "^0.7.0",
"react-native-share": "^1.2.1",
"react-native-web": "^0.11.4"
},
"devDependencies": {
"babel-preset-expo": "^5.1.1"
},
"private": true
}
My end goal is to make a PDF file using HTML in my Expo project.
Please use -
import * as Print from 'expo-print';
instead of -
import { Print } from 'expo-print';
The Expo sdk33 requires the module to be installed and run directly.
expo install expo-print
Modular Imports
With SDK 33, we’re deprecating imports of most modules from the expo package. This means that in a future release, you won’t be able to write, for example, import { FileSystem } from 'expo';. Rather, you’ll need to install the individual packages for each module you use and import from them instead.
You can use the new expo install command to install modules; this command is a wrapper around npm install/yarn add that automatically installs a module version compatible with your SDK version. For example, for the FileSystem module, you would run expo install expo-file-system and then use import * as FileSystem from 'expo-file-system';. This change paves the way for tree-shaking and smaller JavaScript bundles. It also makes moving between the managed and bare workflows simpler.
Imports from the expo package will continue to work in SDK 33 but will generate a warning in the console, and you’ll need to import from the individual packages to make the warning disappear. To make this change easier, we’re providing a codemod that’ll automatically update all of your imports for you.
Home page with description of SDK33
follow this link https://stackoverflow.com/a/71569236/14448694
import * as Print from "expo-print"; import { shareAsync } from "expo-sharing";

React Native with Native Base (Unexpected Token Error)

I have React Native and Native Base configured. When I deploy the app for Android it throws me an error stating that an unexpected token was found near where Container component is present in my code.
My package.json file is:
{
"name": "React Native POC",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"native-base": "^0.5.18",
"react": "15.4.1",
"react-native": "0.39.2",
"react-redux": "^4.4.6",
"redux": "^3.6.0"
},
"devDependencies": {
"babel-jest": "17.0.2",
"babel-preset-react-native": "1.9.0",
"jest": "17.0.3",
"react-test-renderer": "15.4.1"
},
"jest": {
"preset": "react-native"
}
}
Could it be that certain versions are not working well with the other?
Additionally (if it matters) I am using Node version 6.8.1, npm version 3.10.8 and react-native-cli 2.0.0. Also, I have yarn, sinopia and browserify installed globally.
Still a beginner with React Native and I cannot tell if any dependency clashes may be present (obvious or otherwise)
My js file is:
import React, {Component} from 'react';
import {Container, Content} from 'native-base';
export default class ReactNativePOC extends Component {
render() {
return {
<Container> // Error here
<Content>
</Content>
</Container>
}
}
}
There does not seem to be any problem with my setup (excluding native base) as I can run a react native app with default controls however I seem to be getting this error only for native base controls
The return statement should use parentheses instead of braces.
render() {
return (
<Container>
<Content>
</Content>
</Container>
);
}
Please check the basic syntax from docs of React Native
Check NativeBase KitchenSink - An example app with all the UI components of NativeBase.
Since you said you are beginner in React Native, you can check Native Starter Kit - A Starter Kit for React Native + NativeBase + Navigation Experimental + Redux + CodePush Apps