I made a workaround for named Lazy imports in React I want someone to check if this is actually working as lazy import or not.
Toast.js
import { ToastContainer } from "react-toastify";
export default ToastContainer;
App.js
const ToastContainer = React.lazy(() => import("../main/shared/toast"));
return(
<Suspense fallback={null}>
<ToastContainer />
</Suspense>
);
As React official documentation said "currently only supports default exports. If the module you want to import uses named exports, you can create an intermediate module that reexports it as the default. This ensures that tree shaking keeps working and that you don’t pull in unused components."
https://reactjs.org/docs/code-splitting.html
It is working as a lazy component you export this as a default component in 2nd line
The accepted answer, and the documentation that it refers to, are slightly misleading.
lazy() expects a thenable function, meaning that you can load your module and then select which named export you want to import. Using your example, that would become:
React.lazy(async () => {
return {
default: (import("../main/shared/toast")).ToastContainer
}
})
Related
I'm using Stitches to write my CSS in a React application, mainly for the theming and variables. I'm calling createStitches in every component file, like so:
ComponentA.tsx
import { createStitches, styled } from "#stitches/react";
const { createTheme } = createStitches({ theme: {...} });
...
export default ComponentA;
ComponentB.tsx
import { createStitches, styled } from "#stitches/react";
const { createTheme } = createStitches({ theme: {...} });
...
export default ComponentB;
And then I'm importing these components and using them in App.tsx:
import ComponentA from "./components/ComponentA";
import ComponentB from "./components/ComponentB";
function App() {
return (
<div className='App'>
<ComponentA />
<ComponentB />
</div>
)
}
I know I can just call the createStitches in the App.tsx file once, but I like keeping my components self-sufficient, as in they should work without any other extra work. Is this a bad approach, or is this something that is fine to do? Does React call the function many times, or just once? Thanks for any help!
You do not need to call createStitches for every component. This function is to create configuration for your application styling. I don't that you are going to have separate configuration for every component.
This will just cause extra work. Just keep the createStitches in a common file and import it from there
I have this react component. It works just fine for me.
import { Widget } from 'rasa-webchat';
function CustomWidget(){
return (
<Widget
initPayload={"payload"}
socketPath={"/socket.io/"}
customData={{"language": "en"}}
/>
)
}
export default CustomWidget;
But when I try to use it on my next.js website it fails to work.
It gives me a window is not defined error.
I think I resolved this particular error by using the dynamic importer:
import dynamic from "next/dynamic";
const webchat = dynamic(
() => {
return import('rasa-webchat');
},
{ ssr: false }
);
But now I can't figure out how to actually use the widget component from the package.
Am I allowed to import { Widget } from 'rasa-webchat' or is this just not compatible with next.js for some reason? If it's possible, how do I do it?
The syntax for named exports is slightly different. You can use the widget with a dynamic import as follows:
import dynamic from 'next/dynamic';
const Widget = dynamic(
() => import('rasa-webchat').then((mod) => mod.Widget),
{ ssr: false }
);
function CustomWidget(){
return (
<Widget
initPayload={"payload"}
socketPath={"/socket.io/"}
customData={{"language": "en"}}
/>
)
}
export default CustomWidget;
For further details check Next.js dynamic import documentation.
Nextjs is a frame work that allows you to build Static and Server Side rendered apps. So, it uses Nodesj under hood and window is not defined in nodejs. Only way to accessing window in react ssr frameworks is useEffect hook. Your dynamic import solution is right , becuase you are getting file on client side. I hope it makes sense.
Have a great day
is there a way to find out where a react component is used in other components?
for example:
navbar components is used in app.js
import React from 'react';
const Navbar = () => {
return <div>this is Navbar</div>;
};
export default Navbar;
import React from 'react'; import Navbar from './Navbar';
const App = () => {return (<div><Navbar /></div>); };
export default App;
There's two ways to find:
React Developer Tools extension (recommended) tool for debugging. It has a Search bar (text or/regex/)
Most of IDE/Code editors now days has the ability to help you find out component usage
Cheers and I hope this helps
Most IDEs should be able to find references to the component.
Otherwise, a simple search should find it.
I'm currently using React 16 with Suspense and Lazy to code-split my codebase. Although I would like to preload components.
In my example below I got two routes. Is there a way to preload Demo as soon Prime did mount? I've tried to create another dynamic import in the componentDidMount of the Prime page, but React.lazy doesn't seem to get that that's the same file as the dynamic import below.
import React, { lazy, Suspense } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import GlobalStyle from 'styles';
import Loading from 'common/Loading';
const Prime = lazy(() => import(/* webpackChunkName: "Prime" */'modules/Prime'));
const Demo = lazy(() => import(/* webpackChunkName: "Demo" */'modules/Demo'));
const App = () => (
<main>
<GlobalStyle />
<Suspense fallback={<Loading>Loading...</Loading>}>
<Switch>
<Route path="/" component={Prime} exact />
<Route path="/demo" component={Demo} />
</Switch>
</Suspense>
</main>
);
export default withRouter(App);
So I've tried different approaches, for example with and without webpackChunkName and different ways of importing the other component in componentDidMount, as seen below. The first two approaches of importing the file in componentDidMount resulted in a Webpack error shown at the bottom of the image below. Only the third proceeded, but made the file 2.[hash].js in the image, only load after the page was visited, and not on componentDidMount
What am I missing here?
Code of modules/Demo.jsx:
import React from 'react';
import LogoIcon from 'vectors/logo.svg';
import PageLink from 'common/PageLink';
import Anchor from 'common/Anchor';
import CenteredSection from 'common/CenteredSection';
const Demo = () => (
<CenteredSection variant="green">
<LogoIcon />
<PageLink to="/" variant="green">Go to home page</PageLink>
</CenteredSection>
);
export default Demo;
This is incredibly easy to do, I think there is a misunderstanding about what lazy() and Suspense are doing under the hood.
The only expectation that React.lazy() has is that it takes a function that returns a Promise that resolves with a default component.
React.lazy(() => Promise<{default: MyComponent}>)
So if you want to preload, all you have to do is execute the promise yourself ahead of time.
// So change this, which will NOT preload
import React from 'react';
const MyLazyComp = React.lazy(() => import('./path/to/component'));
/*********************************************/
// To this, which WILL preload
import React from 'react';
// kicks off immediately when the current file is imported
const componentPromise = import('./path/to/component');
// by the time this gets rendered, your component is probably already loaded
// Suspense still works exactly the same with this.
const MyLazyComp = React.lazy(() => componentPromise);
The fact that this is a known signature makes it for useful for all sorts of other situations. For instance, I have a bunch of components that rely on the google maps api being dynamically loaded, I was able to create a function that loads the google maps api and then imports the component. I won't detail the internals of this example since it's a tangent, but the point is I made myself a function that does a bunch of async stuff and then returns a Promise with an object of {default: Component}.
import React from 'react';
const MyLazyComp = React.lazy(() => importMapsComponent('./path/to/comp'));
Not sure how much help this will be, but here is a code sandbox that works (Demo gets loaded by componentDidMount). It is a considerably simplified version of your code using create-react-app for the config. Perhaps you can take this as a starting point and morph it gradually closer to your app to see what causes the dynamic import to no longer work as desired.
What's the difference between import React from 'react' and import React { Fragment } from 'react' in context of <React.Fragment>, <Fragment> and <>?
I mean what happen when we import React and { Fragment } in the same line from a module?
Do we create instance of <Fragment> and this is just another few hundreds lines of code under the hood?
Or this is just normal and everybody can do that withouth performance downsides?
Official React blogpost mention that you can do this const Fragment = React.Fragment and they use in in their examples.
But why?
So assume you have an object.
let object = {
foo: '1',
bar: '2',
};
In order to use the value foo you can do the following
object.foo
let { foo } = object
These both are the same, the later mentioned way is called destructing which was introduced in javascript ES6 version.
Now coming to topic for
What's the difference between import React from 'react' and import React { Fragment } from 'react' in context of , and <>?
imagine React as object which has the following features e.g Fragment in this case. You can access it the following ways
1- First way
import React from 'react';
<React.Fragment></React.Fragment>
2-
import React, { Fragment } from 'react';
<Fragment></Fragment>
Now in the second way this is basically importing all React features and also destructing a feature from React which is Fragment. SO you don't have to write React.Fragment again and again.
3-
<></>
This is a babel feature, babel when compiling will convert <></> this into <React.Fragment></React.Fragment>
This is basically syntactic sugar:
import React, { Fragment } from 'react'
Will allow you to write the following:
class MyComponent extends React.Component {
render () {
return (
<Fragment>
<div className="fragment1">Fragment 1</div>
<div className="fragment2">Fragment 2</div>
<Fragment>
)
}
}
Instead of having to write explicitly React.Fragment. Note that you could also write the following if the only imports that you need are React.Component and React.Fragment:
import { Component, Fragment } from 'react'
class MyComponent extends Component {
render () {
return (
<Fragment>
<div className="fragment1">Fragment 1</div>
<div className="fragment2">Fragment 2</div>
<Fragment>
)
}
}
This may also become relevant when using module bundler such as Webpack, so your bundler will only import the required dependencies and it may result in a smaller bundle (AKA your app loads faster). Take a look at Tree Shaking for more details. This ultimately depends on how the imported package exports its modules, as mentioned in the reply above it may have no benefit for React - at the moment - but other libraries may leverage that mechanism. It is usually a good practice to try to keep your imports as strict minimum.
<></> syntax doesn’t support keys or attributes. When element is iterated it will throw the warning message 'Each child in a list should have a unique "key" prop'.
For Example :
{props.items.map(item => (
<>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</>
))}
See docs here https://reactjs.org/docs/fragments.html#keyed-fragments
Well there are no performance downsides, This is just have to do with extra markup. We do named export Fragment like Component that we usually do. As long as if you're concerned about performance, we're already importing from react which means complete react package Because there are not just Component, Fragment we need while exporting component in React Tree. There are under hood dependencies in react package we don't actually import but they are used in our component