We have a project running with React + Material UI, now there is a request to render a certain component(use ComponentA below) by using Ionic(It's not a reasonable requirement however I only discuss from technical perspective here).
From Ionic offical documentation, I did below
install the #ionic/react and #ionic/react-router package
including below css in root component
/* Core CSS required for Ionic components to work properly */
import '#ionic/react/css/core.css';
/* Basic CSS for apps built with Ionic */
import '#ionic/react/css/normalize.css';
import '#ionic/react/css/structure.css';
import '#ionic/react/css/typography.css';
/* Optional CSS utils that can be commented out */
import '#ionic/react/css/padding.css';
import '#ionic/react/css/float-elements.css';
import '#ionic/react/css/text-alignment.css';
import '#ionic/react/css/text-transformation.css';
import '#ionic/react/css/flex-utils.css';
import '#ionic/react/css/display.css';
invoke setupIonicReact() in root component
replace material UI element with ionic element in ComponentA
But it does not work - blank page, and I have to comment out below line
import '#ionic/react/css/structure.css';
Now I can see ionic elements displayed however css styles not applied they look more like html input, button and etc.
I realise there is something wrong however I could not figure out what's the root cause, after searching a while I decide to move step 2)& 3) into that ComponentA. But, new problem coming - setupIonicReact() can not be invoked inside the component, I looked into it and it's pretty simply
export const setupIonicReact = (config: IonicConfig = {}) => {
/**
* By default Ionic Framework hides elements that
* are not hydrated, but in the CE build there is no
* hydration.
* TODO FW-2797: Remove when all integrations have been
* migrated to CE build.
*/
if (typeof (document as any) !== 'undefined') {
document.documentElement.classList.add('ion-ce');
}
initialize({
...config
});
so, I make a simple change - like below
<div className="ion-ce">
<ComponentA />
</div>
now, my chrome keeps loading and there is a blank page alway.
So, I want to stop now and ask for hep, at least to know is it possible using ionic inside a existing project with only certain component?
Related
I've been struggling with a very odd bug(?) with regards to importing an API module into a nested component in a Vue app.
This is the simplest I could reduce the issue down to.
https://codesandbox.io/s/rough-tree-fqj7o
Essentially, the DogsCreate component renders the CreateDogsModal, which is importing the dogs module from the API directory.
As you can see, the codesandbox errors out even on the base URL with the error Cannot read property 'default' of undefined. If running this code locally not on codesandbox, the base URL renders ok, but if you go to /dogs/create, the error then becomes Failed to resolve component: CreateDogsModal.
The things I've found that fix this are:
Commenting out the API import statement in CreateDogsModal (not an option for us, we need to be able to create and import API modules)
Commenting out the TopNav component in main.js (...also not an option for us)
Importing the TopNav component in App.vue with a relative import or #/components/TopNav.vue works fine, but strangely importing CreateDogsModal and CreateTemplate in DogsCreate.vue with a relative import or #/components/[component-name].vue does not. Also, the latter would be somewhat acceptable as a long-term solution, but I'd prefer the #/components shorthand and that still leaves the root cause undetermined.
I'm using the default vue-cli webpack configuration and have checked via vue inspect that the alias seems to be set properly.
I've been spinning my wheels for a week trying to figure this out and just...cannot. Does anyone have any ideas for what may be happening?
It seems like a race condition in Webpack, using parallel builds, but I'm honestly not sure. I can see CreateDogsModal being pulled in from two places, starting from main.js:
'main.js'
- import 'App.vue'
- import '#/components/index.js'
- import and export 'CreateDogsModal.vue'
- import 'router/index.js'
- import '#/views/Dogs/DogsCreate.vue'
- import '#/components/index.js'
- import and export 'CreateDogsModal.vue'
One workaround is to remove the race by making the CreateDogsModal an async component in DogsCreate:
// DogsCreate.vue
import { defineAsyncComponent } from "vue";
import { CreateTemplate } from "#/components";
export default {
name: "DogsCreate",
components: {
CreateTemplate,
CreateDogsModal: defineAsyncComponent(() => import("#/components/CreateDogsModal.vue")),
},
};
demo
I am talking about a big web app that has jquery and bootstrap stuff init.
Part of rewriting this giant app using react and material UI, we are writing component by component. Things work fine in general as we make progress toward making this a react app soon.
Our problem:
When a new react component is loaded into the page, the existing (already loaded) react components will lose some or all styles.
We checked the new component load new style (classes) which are matching the names of existing classes for other already loaded components.
Ex:
As you can see, jss1, jss2, ... MuiCardHeader, MuiGrid, ... were also the names for the previously loaded components and now they are overwritten for the newly loaded component.
Packages.json:
webpack config:
Some component code: we are using make style and in some cases withstyle
Tried too much stuff. But nothing seems to work. On initial load, the map has all the correct material-ui stuff but as soon as I click on a marker and the popup component loads in. Now the map is messed up as some styles are overwritten.
How can we make it so that each component styles are named unique and never conflicts with other stuff?
I checked MUI docs and GitHub issues about kinda similar issue but nothing is working for us.
Any thoughts?
If I add:
import { StylesProvider, createGenerateClassName } from '#material-ui/core/styles';
const generateClassName1 = createGenerateClassName({
seed: 'App2',
});
my custom classes ( like root, mydivstyle) will have the prefix like app2-jss1-root, app2-jss2-mydivstyle, ...
but muiCard, MuiCardHeader, ... still being overwritten.
So after a few trial and error. I was able to solve this.
Basically we don't have a component tree path where you can could add a single class generator because of our app structure at this stage. We will soon have one.
The solution was to wrap every component like.
import { StylesProvider, createGenerateClassName } from '#material-ui/core/styles';
const generateClassName = createGenerateClassName({
seed: 'anyprefix',
});
class ActivityContainer extends Component {
render() {
return (
<StylesProvider generateClassName={generateClassName}>
<componenet/>
</StylesProvider>
);
};
}
I had to do this on the container level, this way any component loaded in that container will inherit this prefix.
No more conflicting class names between components and can load them dynamically.
Not a great way but no other option at least in our case. It will leave more classes on the DOM.
Is it possible to dynamically import precompiled svelte components or whole svelte apps.
And when, how do I compile a single component in svelte 3. I found this approach, but nothing in the docs:
https://github.com/sveltejs/svelte/issues/1576
I want to combine several independent (hosted) Svelte apps on one page to one bigger svelte-app (microfrontend). The goal is, that every sub app can be independent deployed and hosted wherever (may be an own docker container). And any change should be visible in the aggregator app without recompiling it.
I think I wat to do something like this:
https://single-spa.js.org/docs/separating-applications.html
but with no other framework, that is blowing my app and components.
I don't want to use custom components, because of the inflexible styling of the Shadow DOM. I must be able to change css over a global stylesheet.
Has anyone an idea?
Thank you :)
You can take a look at Ara Framework. It has a standalone component named Nova Bridge.
This approach consists of a component that renders a placeholder micro-frontend view will be mounted. Then the component emits a DOM event named NovaMount that is listened by the JavaScript bundle of the micro-frontend to render it and mount it in run-time.
Here an example of the entry point for your micro-frontend.
import { mountComponent, load, loadById } from 'hypernova-svelte'
import Example from './components/Example.svelte'
const render = (name, { node, data }) => {
if (name === 'Example') {
return mountComponent(Example, node, data)
}
}
document.addEventListener('NovaMount', ({ detail }) => {
const { name, id } = detail
const payload = loadById(name, id)
if (payload) {
render(name, payload)
}
})
load('Example').forEach(render.bind(null, 'Example'))
The microfrontend uses hypernova-svelte. You can take a look in this article I wrote for implementing Svelte in Nuxt.
https://ara-framework.github.io/website/blog/2019/08/27/nuxt-js
I'm working on a project where I'm trying to combine ReactJS + Marzipano.
I'm at the stage where I've created my React project using create-react-app, installed Marzipano via npm, and copied / slightly modified some boilerplate code from a Marzipano example here to get it to fit into the React app.
Note I also installed glslify as a dependency in my project, because when I tried to import Marzipano without it, I got the following error:
Module not found: Can't resolve 'glslify'
Note also that glslify is a dev dependency for Marzipano, but not a production one. I'm thinking by installing it as a dependency may be where I tripped things up, but it was throwing the above error without it so not sure what to make of that.
Anyways what's happening now is my browser is rendering a white screen with no errors in the console, however when you click and drag the cursor changes to a closed hand, and the div that I attached Marzipano to via React's ref system has been modified, so Marzipano is definitely doing something.
Below is my App.js file (everything else is a fresh create-react-app installation):
import React, { Component } from 'react';
import './App.css';
import Marzipano from 'marzipano';
class App extends Component {
componentDidMount() {
this.panoViewer = new Marzipano.Viewer(this.pano);
// Create source.
const source = Marzipano.ImageUrlSource.fromString(
"img/test.jpg"
);
// Create geometry.
const geometry = new Marzipano.EquirectGeometry([{ width: 2048 }]);
// Create view.
const limiter = Marzipano.RectilinearView.limit.traditional(1024, 100*Math.PI/180);
const view = new Marzipano.RectilinearView({ yaw: Math.PI }, limiter);
// Create scene.
const scene = this.panoViewer.createScene({
source: source,
geometry: geometry,
view: view,
pinFirstLevel: true
});
// Display scene.
scene.switchTo();
}
render() {
return (
<div>
<div ref={pano => this.pano = pano} />
</div>
);
}
}
export default App;
The first (and only) time the render method is called, the div which you attach the ref to has no content and therefore is rendered with a height of zero.
Marzipano then creates the scene in this div, but as it reads the dimensions of the container element, it renders a canvas with zero height.
To fix this, either set a specific height on the div (for example using the style attribute) or give it a height of 100% and do the same in index.css for html, body and #root
I am trying to decide the best route to go for distributing a component that others can theme. They may need to change the html structure as well as the css/bootstrap styling. (I am using react-bootstrap with the component.
The only way I can see to do this is to make a component folder with all of the subcomponents in src/themes/default, src/themes/awesome, etc and then import them into the main component which people can then call by doing something like this...
This is just a concept, it probably isn't completely valid
import default from './themes/default/index.js`
import awesome from './themes/awesome/index.js`
const themes = {
default,
aweosme,
}
const MyComponent = ({ theme, otherprop }) => {
return (
<themes.default otherprop={otherprop} />
)
}
then if someone wanted to contribute a theme, they would have to write a whole component complete with html structure in the jsx and inline styles to go along with it. It would require them to be familiar with react, but I cannot see another way to do it unless I have missed something...
What do you think?