I am using single spa to create a my react microfrontends, in one of the MFE(microfrontend) I need to dynamically import a ".js" from another MFE and render the component , for that I am using systemjs import
Below is a sample code on how the child component exposes a function to export a js file in the main files
export function getcode() {
return import("./views/rk.js");
}
and in the parent component I use react.lazy to import the js file from the function and render as component
const Test = React.lazy(() =>
import("#Test/react-singlespa").then((mod) => mod.getcode())
);
and render the above const as below using
<React.Suspense fallback="Loading ...">
<Test/>
</React.Suspense>
I don't have issue while running the code in development mode but in the production mode the styles are messed up for first load but subsequently the styles are fine.
The question seems to be common with material ui issues import of webpack, but none of the solutions online seem to help. I tried every possible solution given in the below links
https://github.com/mui-org/material-ui/issues/15610
https://material-ui.com/getting-started/faq/#i-have-several-instances-of-styles-on-the-page
Assuming this is something that has to be done with Single-spa framework ...any help in this regard is greatly appreciated
Related
I'm setting up a component library with React, Storybook, Typescript and Material UI. One of the main targets of the library is to re-export components that are imported from MUI (with a bit of config on top of them). I stumbled upon an issue where one of the components is not being rendered as intended when used in another React app. The component I am talking about is the Stepper component. Below is what I have now:
Stepper.tsx
import Stack from '#mui/material/Stack';
import MUIStepper, { StepperProps } from '#mui/material/Stepper';
const Stepper = (props: StepperProps) => {
return (
<Stack sx={{ width: '100%' }} spacing={4}>
<MUIStepper {...props}></MUIStepper>
</Stack>
);
};
export default Stepper
This is going to be built as a library using rollup.
I am not going to paste the entire rollup config here, but these are the plugins the config is using:
import babel from '#rollup/plugin-babel';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import filesize from 'rollup-plugin-filesize';
import autoprefixer from 'autoprefixer';
import typescript from "rollup-plugin-typescript2";
import dts from "rollup-plugin-dts";
After the process of building and publishing the library to an npm registry, I am trying to use it in some other React application, but some of the styles/internal components of the Stepper are totally missing (ex: active step css, step connectors etc.). The usage of the Stepper component is the same as in the official docs and it works perfectly with the original Stepper component.
Can you think of any configuration I am missing? It looks like something is lost along the way while building the library, but not sure what. Either that or the children components do not receive props properly.
I can provide further insight into this if necessary, but I didn't want to clutter the post anymore that it already is.
The Stepper component expects two or more Step components as children. To fix this, you need to pass props.children to the Stepper component.
import Stack from '#mui/material/Stack';
import MUIStepper, { StepperProps } from '#mui/material/Stepper';
const Stepper = (props: StepperProps) => {
return (
<Stack sx={{ width: '100%' }} spacing={4}>
<MUIStepper {...props}>{props.children}</MUIStepper>
</Stack>
);
};
export default Stepper;
Answering my own question here:
It looks like this behavior si encountered whenever we deal with components that use the Context API internally. Somehow, the context gets messed up if we use the root component from our library and other descendant components from MUI. Simply importing and re-exporting descendant components and using them from owr library as well fixes this issue, although I would want to avoid that. Until then, I created an issue on the github page to see if it is a bug on their side or just an intended behavior which affects my case here.
All in all, it is not really a rollup config issue. Transpilation and bundling work as intended.
Issue link: https://github.com/mui/material-ui/issues/33320
Could you please help with the following?
We use Ionic with React in a team having 2 distinct projects.
We need to style these Ionic components a little differently.
I need to share these a-little-differently-styled Ionic components with another team for code re-use.
I would like to showcase these styled Ionic components using Storybook to the UX team and say "this is how a button looks like"
To begin with I just added the styling in a css file and imported that file in the root React page.
But it would be nice to just encapsulate component + styling in a re-usable isolated component that other people can re-use without having to import custom css files.
I am thinking of :
import { IonButton } from "#ionic/react";
import styled from "styled-components";
const StyledIonButton = styled(IonButton)`
// some custom css styling here
`;
const MyIonButton = () => <StyledIonButton {...props} />;
export default MyIonButton;
Now, I can track/export above component using e.g Bit.dev and have the other team consume it via npm-install.
However, I dislike :
a) changing the name from "IonButton" to "MyIonButton"
b) having to wrap each and every Ionic component as shown above
I would like myself and the other team to just use Ionic components in the standard way e.g
import { IonButton } from "#ionic/react";
...
<IonButton>Close</IonButton>
BUT having these base building-blocks/components styled in a certain way.
Could you please describe to me the right approach please? Many thanks for your time
I am trying to upgrade from react-intl v 2.3.0 to 4.5.1. I have run into a few issues around the injectIntl HOC since the upgrade. I have a shared component library within a monorepo that is imported into different features (combination of imported shared and local unique components in a separate part of the repo). However, my IntlProvider lives in my shared components library and we import a component called AppShell that includes any needed providers (including intl) that wraps the top level of every feature.
I followed advice found on an issue on the formatjs repo and deleted the react-intl version from my shared component library. This solved most of my issues with a few caveats.
Note, all examples below are using a feature folder with react-intl version 4.5.1, and a shared component library having no version of react-intl installed
Fix attempt 1
If I try to use the injectIntl HOC from react-intl the component will not render on the page and I get the following errors:
code example (AppShell wrapper component lives in the top level ReactDOM.render function):
import { FormattedMessage, injectIntl } from 'react-intl';
// shared component library
import { Alert } from '#shared/components/alert';
// component custom to feature, also can contain shared components
import WorkspaceListContainer from './workspaceListContainer';
import messages from './messages';
export class AppLifecycleMenu extends Component {
render() {
const deleteAlertTitle = this.props.intl.formatMessage(
messages.deleteAlertTitle,
{ alertName: name }
);
return (
<Fragment>
<WorkspaceListContainer />
<Alert
title={deleteAlertTitle}
okButtonText={<FormattedMessage {...messages.deleteOkButton} />}
cancelButtonText={<FormattedMessage {...messages.deleteCancelButton} />}
/>
</Fragment>
);
}
}
export default injectIntl(AppLifecycleMenu);
Note, in a lot of our shared components, intl messages can be passed in as props and some components are wrapped in their own injectIntl HOC to intl default versions of props (like a default button label).
Fix attempt 2
However, if I import an injectIntl helper we have in our shared resource library, the component renders but still displays an error message:
injectIntlHelper code:
// only apply intl in non-test environments
export default Component => process.env.NODE_ENV === TEST_ENV ? Component : injectIntl(Component);
code example (AppShell wrapper component lives in the top level ReactDOM.render function):
import { FormattedMessage, injectIntl } from 'react-intl';
// shared component library
import { Alert } from '#shared/components/alert';
import injectIntl from '#shared/utilities/injectIntl';
// component custom to feature, also can contain shared components
import WorkspaceListContainer from './workspaceListContainer';
import messages from './messages';
export class DeleteWorkspaceAlert extends Component {
render() {
const deleteAlertTitle = this.props.intl.formatMessage(
messages.deleteAlertTitle,
{ alertName: name }
);
return (
<Fragment>
<WorkspaceListContainer />
<Alert
title={deleteAlertTitle}
okButtonText={<FormattedMessage {...messages.deleteOkButton} />}
cancelButtonText={<FormattedMessage {...messages.deleteCancelButton} />}
/>
</Fragment>
);
}
}
export default injectIntl(AppLifecycleMenu);
component tree with intlprovider:
Error message:
Fix attempt 3
I also tried only having react-intl installed in the shared resource library but that results in this error message:
Environment
I have tried going down versions in react-intl, but this issue persists back down into the 3.0 and up versions
I've been trying different combinations and looking online for a few days, are there any other changes I can make to get rid of these errors? Is anything jumping out as something I am missing adding or updating between versions?
For anyone who comes across this, my issue was solved by following/modifying the fix from the issue: https://github.com/formatjs/formatjs/issues/1620
Unlike the issue linked above, my projects IntlProvider lives in the shared resource library and is exported to wrap components. Therefore I deleted the react-intl dependency from all folders other than my shared resource library and exported any needed components from there.
So my imports in my non-shared components folder would look like
import injectIntl, { FormattedMessage, FormattedDate } from '#shared/utils/intl';
with component(s) in my shared library that have files that look like this
import { FormattedMessage } from 'react-intl;
export FormattedMessage;
Relevant quote from the issue:
I think the reason [having multiple dependencies] worked with older version is old React context API. New React context API rely on same reference. You project instantiates react context from different node_modules thus contexts are not same reference. This also means you are bundling react-intl twice in your application.
I'm new in Nextjs and I want to add a list of components and utilities to all of my pages in Nextjs. How can I make them all available in my components without importing them one by one.
Also some utilities might be needed in getInitialProps function in pages like axios or in my case client of Apollo.
I don't expect some one write me a whole config file for Nextjs.config just help me to understand the configuration of next deeper.
thanks in advance
I would suggest to do dynamic import on each page, for each component and utility instead of making components global. By doing so Next.js will create a small chunks or "pages" without any unused components.
If you load components globally, every page would increase in size but actually not use these components or utilities. It defeats a purpose of code-splitting.
It breaks modularity of your code, because components/pages (modules) will depend on some global utilities implicitly.
If you have too many imports in your component or page, probably, it's a sign to encapsulate that extra functionality by extracting it to it's own component.
Controversially, you could try to add global utilities in Custom "App"
For example, you could pass a React component to all Next.js pages via props of custom App.
_app.js
import Icon from '../components/Icon';
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} icon={Icon} />
}
As all pages are instancing from the App, every page would have this component in the props.
index.js
const Home = props => (
<div>
<props.icon><props.icon/>
</div>
);
If you have many components you could group them into list and assign to a single prop, so you can use it like:
index.js
const Home = props => (
<div>
<props.components.icon/>
<props.components.anotherIcon/>
</div>
);
On a side note, it's suggested to use getStaticProps and getServerSideProps for pages instead of getInitialProps since Next.js 9.3.
Suggested reading:
Next.js Data fetching (getInitialProps)
React.js Code-Splitting
I'm trying to use Atomize (https://atomizecode.com/) with Gatsby JS (https://www.gatsbyjs.org/) and while it is successfully installed, the atomize components are not being rendered to the page.
I am trying to import a button to start "Hey", and while it renders something it is not the standard button component. Also, even though the button component is imported, I get the warning that reads it is not being used.
I am wrapping atomize around gatsby app by the following way:
import React from "react"
import { StyleReset } from "atomize"
export const wrapRootElement = ({ element }) => (
<>
<StyleReset />
{element}
</>
)
Did you install styletron toolkit?
According to their docs it's a dependency and looking at their package.json it's defined under peerDependencies which means it won't get installed along with atomize.
Styletron's docs sugggets using gatsby-plugin-styletron for Gatsby.
Hope that helps.