How to make Remix work with react material ui icons - material-ui

I'm working on a POC with remix + react material (as that's what we use in our main app). I've gotten most things working but I can't get icons to work. Any page that has an icon just hangs and remix yells at me.
Lambda :\Users\chanp\git\my-remix-app\server timed out after 5 seconds
Here's my entry.client. I stole this from the semi-official remix + mui app. I updated the hydrate to work with react 18 (hydrateRoot instead of just hydrate)
import { CacheProvider } from "#emotion/react";
import CssBaseline from "#mui/material/CssBaseline";
import { ThemeProvider } from "#mui/material/styles";
import * as React from "react";
import { useState } from "react";
import { hydrate } from "react-dom";
import { RemixBrowser } from "#remix-run/react";
import createEmotionCache from "./createEmotionCache";
import ClientStyleContext from "./styles/ClientStyleContext";
import muiTheme from "./styles/muiTheme";
import { ThemeProvider as EmotionThemeProvider } from "#emotion/react";
import Layout from "./src/components/Layout";
import { hydrateRoot } from "react-dom/client";
const container = document.getElementById("app");
// const root = hydrateRoot(container, <App tab="home" />);
interface ClientCacheProviderProps {
children: React.ReactNode;
}
function ClientCacheProvider({ children }: ClientCacheProviderProps) {
const [cache, setCache] = useState(createEmotionCache());
function reset() {
setCache(createEmotionCache());
}
return (
<ClientStyleContext.Provider value={{ reset }}>
<CacheProvider value={cache}>{children}</CacheProvider>
</ClientStyleContext.Provider>
);
}
hydrateRoot(
document,
<ClientCacheProvider>
<EmotionThemeProvider theme={muiTheme}>
<ThemeProvider theme={muiTheme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<RemixBrowser />
</ThemeProvider>
</EmotionThemeProvider>
</ClientCacheProvider>,
);
Versions
React v18.2
Remix v1.6
Other verions from package.json
"#emotion/react": "^11.10.0",
"#emotion/styled": "^11.10.0",
"#mui/icons-material": "^5.8.4",
"#mui/lab": "^5.0.0-alpha.93",
"#mui/material": "^5.9.3",
"#mui/styled-engine-sc": "^5.9.3",
"#mui/styles": "^5.9.3",
"#mui/x-date-pickers": "^5.0.0-beta.4",
I'm not sure what else would be pertinent to this question. Just let me know if I need to provide more details.

Doesn't work
import { Sensors } from '#mui/icons-material'
Works
import Sensors from "#mui/icons-material/Sensors";
I also had to add
"#mui/icons-material"
to
serverDependenciesToBundle
in the Remix.config.js
Guessing ESBuild is to blame here. Still learnig the quirks so an edit of this answer as to why would be good. Or maybe a link to a resource to a more generic explanation as to why.

Related

Preload a script in react-native-webview

I am using react-native-webview so i want to load script in this. So as the webview calls it loads my script and show my content everytime.
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { WebView } from 'react-native-webview';
// ...
class MyWebComponent extends Component {
render() {
return <WebView source={{ uri: 'https://reactnative.dev/' }} />;
}
}
So i want to that i will load a Script in the package react-native-webview so that it will load script once and then show my content according to that. So let me know in which file i can make changes in the package to load some script intially.

How to use echarts-gl with echarts

I am learning to use echarts.js for my project.
I would like to know to use the extension echarts-gl (for 3D graphics) with ES modules. The documentation is very succinct and I am just a noobie.
In fact, I am trying to use echarts-gl together with the echarts-for-vue, anyone have tried it?
My main.js looks like this:
import Vue from 'vue';
import App from './App.vue';
import { plugin } from 'echarts-for-vue';
import * as echarts from 'echarts/esm/echarts';
import 'echarts/esm/chart/line';
import 'echarts/esm/chart/bar';
import 'echarts/esm/component/title';
import 'echarts/esm/component/tooltip';
import 'echarts/esm/component/legend';
import 'echarts/esm/component/toolbox';
import 'echarts/esm/component/polar';
import 'echarts/esm/component/visualMap';
// require('echarts-gl/lib/echarts-gl');
// import '../assets/echarts-gl.js';
// import 'echarts-gl/lib/component/grid3D';
// import 'echarts-gl/lib/chart/surface';
Vue.config.productionTip = false;
Vue.use(plugin, { echarts });
new Vue({
render: (h) => h(App),
}).$mount('#app');
I don't know where or how to include the imports for echarts-gl. Do I need webpack configuration?
Sorry about my lack of expertise.
Thanks!
For me it worked when I just imported it like this:
import 'echarts';
import 'echarts-gl';
Also make sure to use a compatible version of echarts-gl with echarts.
(
"echarts": "4.9.0",
"echarts-gl": "1.1.2",
"vue-echarts": "4.1.0",
)

How to hide header on scroll in ionic 4?

I wanted to know how I can hide a header in Ionic 4 by scrolling down the page, and re-show it when scrolling up.
I found many solutions on how to do that, but they all turned out to not working or being out-of-date.
So I collected all piece of information I could find to provide this answer.
Thanks to this video I got it to work.
First of all call ionic g directive directives/hide-header. You can of course replace directive/hide-header with your own path and name.
hide-header.directive.ts
import { Directive, HostListener, Input, OnInit, Renderer2 } from '#angular/core';
import { DomController } from '#ionic/angular';
#Directive({
selector: '[appHideHeader]'
})
export class HideHeaderDirective implements OnInit {
#Input('header') header: any;
private lastY = 0;
constructor(
private renderer: Renderer2,
private domCtrl: DomController
) { }
ngOnInit(): void {
this.header = this.header.el;
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'transition', 'margin-top 700ms');
});
}
#HostListener('ionScroll', ['$event']) onContentScroll($event: any) {
if ($event.detail.scrollTop > this.lastY) {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', `-${ this.header.clientHeight }px`);
});
} else {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', '0');
});
}
this.lastY = $event.detail.scrollTop;
}
}
After that, in your template:
<ion-header #header>
<ion-toolbar><ion-title>Test</ion-title></ion-toolbar>
</ion-header>
<ion-content scrollEvents="true" appHideHeader [header]="header">
</ion-content>
Take care of the scrollEvents, appHideHeader and the [header] attributes! The last one takes the header element as argument, in this case #header.
Most of the code is the same as shown in the video. I changed the host-property from the #Directive and used the more up-to-date HostListener.
If you want to use the directive in more than one directive, you need to create a SharedModule.
To do so, create the module with ng g module shared. After that, add the HideHeaderDirective to the declarations and the exports array.
shared.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HideHeaderDirective } from './directives/hide-header.directive';
#NgModule({
declarations: [HideHeaderDirective],
exports: [HideHeaderDirective],
imports: [
CommonModule
]
})
export class SharedModule {}
Now add the shared module to all the modules you want to use the directive in.
Note: You cannot import the directive in app.module.ts and use it in a submodule! You have to import the shared module in every direct module you want to use the directive in.
My current versions of node, npm and ionic:
For this you can just place the ion-header before the ion-content. this is the simple answer for that.

Dynamically rendering react components

I'm new to reactjs and I'm having a hell of a time understanding this bug.
I've read this, and it seems like the solution is there but I'm drawing a blank on how to implement this correctly:
https://facebook.github.io/react/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized
I am trying to render components based on classNames of clicked elements. The classNames match to component names. When I click an element it calls a function that sets the state of my app to that elements className. I then render the component based on the new state.
When testing, if I place the component directly into my app (not rendering the component name dynamically), it works just fine. But when i render the component name dynamically react thinks it's a built-in DOM element and doesn't render properly at all.
In this image you can see both components, rendered next to each other:
both components, first directly added, and the second with the name rendered dynamically
here is my app component code that is rendering everything:
import React, { Component } from 'react';
import logo from '../logo.svg';
import '../css/App.css';
import menus from '../menus';
import MainNav from './MainNav';
import Products from './Products';
import Demos from './Demos';
import Industry from './Industry';
import Customers from './Customers';
import Trials from './Trials';
import Contact from './Contact';
import Newsroom from './Newsroom';
import About from './About';
import Home from './Home';
class App extends Component {
constructor() {
super();
this.chooseComponent = this.chooseComponent.bind(this);
this.state = {
allMenus: menus,
componentMenu: menus,
//sets initial component to load, changes on each click to the clicked component
clickedComponent: Home
};
}
chooseComponent(event) {
//save the classname of the menu i click
var clickedComp = event.target.className;
//saves a reference to a json object for later use
var menu = menus[clickedComp];
//adds those two vars to the state
this.setState({
componentMenu: menu,
clickedComponent: clickedComp
});
}
render() {
//saves a var for rendering the currently clicked component
var ActiveComponent = this.state.clickedComponent;
return (
<div className="App">
<MainNav choose={this.chooseComponent}/>
//renders the components directly without issue
<Products menuData={this.state.componentMenu} />
//renders the component dynamically with problems
<ActiveComponent menuData={this.state.componentMenu} />
</div>
);
}
}
export default App;
here is and example of one of my component being rendered in the App that's giving problems:
import React from 'react';
import products from '../products';
import ProductsMenu from './ProductsMenu';
import Platform from './Platform';
import Applications from './Applications';
import ExMachina from './ExMachina';
import ProductsHome from './ProductsHome';
import Submenu from './Submenu';
import menus from '../menus';
class Products extends React.Component {
constructor() {
super();
this.showContent=this.showContent.bind(this);
this.state = {
productsOverview: products,
content: <ProductsHome />
}
}
render(props) {
return (
<div className="content">
{this.state.content}
</div>
);
}
}
export default Products;

Ionic SqlStorage is not defined

I'm trying to use SqlStorage in an ionic app. I'm getting the error in the title. I'm guessing I need to include SqlStorage but I'm not sure where. My code looks a lot like what's in the docs http://ionicframework.com/docs/v2/api/platform/storage/SqlStorage/ . How do you include SqlStorage?
var prefrences = {
foo: bar
}
let storage = new Storage(SqlStorage);
storage.set('storedPreferences', preferences);
Add SqlStorage to your list of 'include' packages via import statement. i.e
import {SqlStorage} from 'ionic-angular';
For example
import {SqlStorage,...} from 'ionic-angular';
#Page({
templateUrl: 'path/to/template'
})
export class MyPage {
constructor(){
let storage = new Storage(SqlStorage);
...
}
...
}