What is a Suspense
Take a look at how the React site explains it.
Suspense lets components “wait” for something before rendering. Today, Suspense only supports one use case: loading components dynamically withReact.lazy. In the future, it will support other use cases like data fetching.
The specific links
In general, Suspense allows components to be in a wait-like state, waiting for some behavior to end before rendering. Suspense currently only supports scenarios where components are dynamically loaded with react. lazy. Other scenarios such as data retrieval will be supported in the future.
// This component is loaded dynamically
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
// Displays <Spinner> until OtherComponent loads
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}
Copy the code
In general, it is available in version 16.6.0 of Replay 2018, but it is not used in code at all. In general, it is not used in code at all.
The scenario
In React projects, we often use large components, such as loading maps, Echarts charts, rich text editors, etc. Try out how to optimize your experience in similar scenarios step by step.
NPM packages such as @tinymce/ tinymce-React are available in libraries such as Tinymce/Tinymce-React. However, in practice, NPM packages such as @tinymce/ Tinymce-React are available in libraries such as Tinymce. This kind of component is often not used as soon as the user enters the page, so from the perspective of the performance of the first screen rendering, we will use lazy loading of components and other methods, so there are waiting conditions during asynchronous loading, resulting in blinking of components and other conditions. From the perspective of engineering optimization, especially in micro-front-end scenarios, such large components will be repeatedly packaged if they are used in multiple projects at the same time. It is recommended to exclude them from the packaging scope and use UMD (using the browser’s own cache) or package them separately.
\
We still use umi to quickly build a simple environment
mkdir myapp && cd myapp
npx @umijs/create-umi-app
Copy the code
Then we introduce tinymce, a rich text editor
npm install --save @tinymce/tinymce-react
Copy the code
Then we create a file named editor. TSX in the SRC /pages directory. We copy the code from tinymce’s official React example
import React, { useRef } from 'react'; import { Editor } from '@tinymce/tinymce-react'; export default function App() { const editorRef = useRef(null); const log = () => { if (editorRef.current) { console.log(editorRef.current.getContent()); }}; return ( <> <Editor onInit={(evt, editor) => editorRef.current = editor} initialValue="<p>This is the initial content of the editor.</p>" init={{ height: 500, menubar: false, plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen', 'insertdatetime media table paste code help wordcount' ], toolbar: 'undo redo | formatselect | ' + 'bold italic backcolor | alignleft aligncenter ' + 'alignright alignjustify | bullist numlist outdent indent | ' + 'removeformat | help', content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }' }} /> <button onClick={log}>Log editor content</button> </> ); }Copy the code
Then add route configuration reference in. Umirc. ts, enable dynamicImport on demand, and disable the loading effect of umi itself
dynamicImport: {
loading: '@/components/loading',
},
routes: [
{ exact: true, path: '/', component: 'index' },
{ exact: true, path: '/editor', component: 'editor' },
],
Copy the code
Create a new loading. TSX under SRC/Components
import React from 'react';
export default () => <></>;
Copy the code
Then we add a jump button to index. TSX
import { Link } from 'umi'; import styles from './index.less'; Export default function IndexPage() {return (<div> <h1 className={styles.title}>Hello, </h1> <Link to="/editor"> to find the rich text editor </Link> </div>); }Copy the code
Then let’s do NPM start and see what happens
After switching routes, we find a blank screen and load the rich text Editor. If we want to change it so that the user is aware that the interface is loading to give a direct feedback, we can use react.suspense to create LoadEditor. Specify the/Editor route to loadedian.tsx
import React, {Suspense, useEffect} from 'react'; const EditorComponent = React.lazy(() => import('./Editor')); export default function LoadEditor() { return ( <div> <Suspense fallback={<div Style ={{height:528,width:'100%',display:'flex',alignItems:'center',justifyContent:'center',fontSize:28}}> editor loading!! </div>}> <EditorComponent/> </Suspense> </div> ); }Copy the code
And then we look at the effect,
The loading box we wrote by ourselves disappeared in a moment. The page was still loaded with external resources referenced by the rich text editor in a white screen, and it took some time to display it. Why is this so?
In fact, the students who know the lower level already know that when the loading effect comes out, the component is indeed in the loading process. The lazy loading speed of the component itself is very fast, but it does not mean that the external resources it depends on have been loaded. The operation is like a tiger, and the result is 0-5.
In the actual scene, the size of the component itself is often in an acceptable range, more interface is used to process the data delay, such as the examples from the community portal, in such cases can solve many problems, don’t need to go inside the component that a variable symbol whether the current data loading is completed, and then according to the state of the interface returned to switch.
import createResource from "./magical-cache-provider"; const dataResource = createResource(id => fetchData(id)); class DynamicData extends Component { render() { const data = dataResource.read(this.props.id); return <p>Data loaded ? </p>; } } class App extends Component { render() { return ( <Suspense fallback={<p>Loading... </p>}> <DeepNesting> <DynamicData /> </DeepNesting> </Suspense> ); }}Copy the code
How to transform
Going back to our example above, which is the loading scenario where there are other resources in the component, what is the solution?
Here first sell a mystery, looking forward to the next decomposition 😎
For more information on React.Suspense and React. Lazy, please refer to the React website and other posts in the community.
\
\
For more content, you can follow the public account meow Dad’s workshop