Skip to main content

React Performance - react.lazy for component, large data loading, react-router-dom

 

1. To address these problems, we setup route-based code splitting using the react-loadable npm package. We then moved to React.lazy and Suspense despite it not supporting server-side rendering at that time. We switched because there was now a built-in way to handle dynamic imports.


2. Rendering these items was putting a lot of strain on the browser and we saw a lot of jank. To fix this, we used an npm module called react-window which provides a higher-order component that controls the rendering of long lists. It does not render items that are not immediately visible. It supports lazy loading, custom properties, and event handlers. This gave us list rendering at 60fps.

https://www.apollographql.com/docs/react/pagination/core-api/
https://codesandbox.io/s/5wqo7z2np4?file=/src/App.js:0-2108
import React, { createRef, Fragment, PureComponent } from "react";
import { FixedSizeList as List } from "react-window";
import InfiniteLoader from "react-window-infinite-loader";

const LOADING = 1;
const LOADED = 2;
let itemStatusMap = {};

const isItemLoaded = index => !!itemStatusMap[index];
const loadMoreItems = (startIndex, stopIndex) => {
for (let index = startIndex; index <= stopIndex; index++) {
itemStatusMap[index] = LOADING;
}
return new Promise(resolve =>
setTimeout(() => {
for (let index = startIndex; index <= stopIndex; index++) {
itemStatusMap[index] = LOADED;
}
resolve();
}, 2500)
);
};

class Row extends PureComponent {
render() {
const { index, style } = this.props;
let label;
if (itemStatusMap[index] === LOADED) {
label = `Row ${index}`;
} else {
label = "Loading...";
}
return (
<div className="ListItem" style={style}>
{label}
</div>
);
}
}

export default function App() {
return (
<Fragment>
<p className="Note">
This demo app mimics loading remote data with a 2.5s timer. While rows
are "loading" they will display a "Loading..." label. Once data has been
"loaded" the row number will be displayed. Start scrolling the list to
automatically load data.
</p>
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={1000}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<List
className="List"
height={150}
itemCount={1000}
itemSize={30}
onItemsRendered={onItemsRendered}
ref={ref}
width={300}
>
{Row}
</List>
)}
</InfiniteLoader>
<p className="Note">
Check out the documentation to learn more:
<br />
<a href="https://github.com/bvaughn/react-window-infinite-loader#documentation">
github.com/bvaughn/react-window-infinite-loader
</a>
</p>
</Fragment>
);
}


https://www.infoq.com/articles/reduce-react-load-time/

3. use Link instead of href

import { Link, useHistory } from 'react-router-dom' <Link
to={{
pathname: `/homes`,
}}
>
Search
</Link>
instead of this:
<Button href="/homes" color="primary" startIcon={<ArrowBackIcon />}>
Search
</Button>

Comments

Popular posts from this blog

for loop in javascript - promise - .eslintrc for "for of"

the vast majority of cases  map ,  forEach ,  find  etc. can be used.  async function printFiles () { const files = await getFilePaths(); await Promise.all(files. map (async (file) => { const contents = await fs.readFile(file, 'utf8') console.log(contents) })); } const inventory = [ { name : 'apples' , quantity : 2 } , { name : 'bananas' , quantity : 0 } , { name : 'cherries' , quantity : 5 } ] ; const result = inventory . find ( ( { name } ) => name === 'cherries' ) ;   function getFirstMatching(array) { for (let item of array) { const result = heavyTransform(item); if (result) { return result; } } } Specifically this shuts down the whole no-restricted-syntax. If you want to cherry-pick, here is the current definition: 'no-restricted-syntax' : [ 'error' , { selector : 'ForInStatement' , message...

Apollo client - cache APIs - auto update cache - erase cache - reactive variables - deletion - addition

Apollo Client 3  Local only fields Reactive Variables const cache = new InMemoryCache ( { typePolicies : { Todo : { // If one of the keyFields is an object with fields of its own, you can // include those nested keyFields by using a nested array of strings: keyFields : [ "date" , "user" , [ "email" ] ] , } } , } ) ; This internal data is intended to be easily  JSON-serializable , so you can take a snapshot with  cache.extract() , save it somewhere, and later restore with  cache.restore(snapshot) . Here’s a mutation called  EditTodo  that returns the new  todo  value in the mutation response. mutation EditTodo ( $id : Int ! , $text : String ! ) { editTodo ( id : $id , text : $text ) { success todo { # <- Returning it here id text completed } error { ... on TodoNotFoundError { message } ... on TodoValidationE...

window.URL.createObjectURL is not (yet) available in jest-dom - testing scenario

Since  window.URL.createObjectURL  is not (yet) available in jest-dom, you need to provide a mock implementation for it. Don't forget to reset the mock implementation after each test. describe ( "your test suite" , () => { window . URL . createObjectURL = jest . fn (); afterEach (() => { window . URL . createObjectURL . mockReset (); }); it ( "your test case" , () => { expect ( true ). toBeTruthy (); }); });