WYSWYL With React on screen and async fetch

The what…

In case you might be wondering just what in the hell WYSWYL is, its

What you see is What you load.

What does it mean for you as a developer, or you as a user? Well, in our quest for designing websites with faster load times and better responsiveness, WYSWYL might just speed up things for users visiting your site and give you — the developer an opportunity to proudly declare to your management that you have designed a lighting fast website. And your users will testify to that fact.

Now before we proceed — a small disclaimer. This article is strictly meant for initiated/seasoned React developers and if you are new to react, this article might not be as intuitive to you. Even so, if you are feeling fairly brave and think you can get a hang of it. By all means proceed..

The how…

React on screen is a nifty little package available at

(Big shout out to Fadi Khadra who is just about to make life for a lot of people very very easy)

an npm install command will easily install this package for your react project, ready to be imported in whichever component that requires the magic of WYSWYL.

$ npm install --save react-on-screen
$ yarn add react-on-screen

Use NPM or yarn to install.

How does React on screen help? What would you do to cast the WYSWYL spell? So many questions. Well here come the answers..

const whyWeDo =() => {

So now that you have installed react on screen, what can you do with it? Well here we go..

TrackVisibility is the component that helps you facilitate the functionality of React on screen. Basically, its a wrapper component that wraps your component’s tag and keeps track of when your component is visible in the viewport to the user. So essentially, you as the developer can always keep track of what the user is seeing on their screen. This can be very useful as given the fact that you know that a component is visible to the user as he browses the website, you can do little bit of second guessing and take actions to load data asynchronously in the background. Why would you do this?

Well, most websites these days are single page applications. React is a great library to create a single page app. Essentially, React components have a hierarchical structure and as the user takes actions on the screen by browsing/scrolling/clicking buttons, links etc. these actions could change the view of the screen and swap out divs dynamically.

With React the usual paradigm is to load data when a particular component is loaded into the viewport. This is minimalistic and ensures you only load what is required to render your component.

But sometimes, there may be a case where the user is looking at a component in the viewport and on clicking that, the next component which is loaded has to be fetched from a server sitting across the world. This will result in latency issues and the data fetch would add to the time it takes to render the component. A very good use case for this would be a news website. The front page might only present headlines in the form of links to the user. But when the user clicks on a headline, they are taken to the actual news article. Text and images are to be loaded from across the wire and this might take time, especially if you as a user are on a slow network connection. This can be very frustrating and you would know because God knows, I’ve been quite frustrated by slow load times in websites.

So where does React on screen come in?

Well, with the WYSWYL paradigm, with TrackVisibility you wrap the <Headline> component. You track the visibility of the headline to the user as he browses your site. Now as he scrolls to the site and a headline appears in the viewport, you do an async fetch behind the scenes as and when a <Headline> component appears in the viewport. So essentially, you are loading the entire Article in the background as the user browses the site. Then when they are ready to click, you will have already fetched the Article data in the background, into the browser. So the network trip is avoided and the user is able to see the article instantaneously.

}

The code…

So I mentioned that you will wrap the component you want to track with TrackVisibility. It would be something like this..

render() {
const list = [];
for (let i = 0; i < 5; i++) {
list.push(
<React.Fragment key={i}>
<TrackVisibility>
<InnerContent index={i}/>
</TrackVisibility>
<hr />
</React.Fragment>
);
}
return (
<div>

<div>{list}</div>
</div>
);
}

As you can see, I have wrapped the component I want to track — InnerContent with the TrackVisibility wrapper.

The InnerContent component itself is a simplistic collections of divs with numbers representing the sequence number of the div on the screen.

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import throttle from 'lodash.throttle';
import shallowequal from 'shallowequal';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import './IndexContent.css';
import DataStore from './DataStore'
import regeneratorRuntime from "regenerator-runtime";

async function getHawaiiGovData() {
let response = await fetch('https://data.hawaii.gov/api/views/usep-nua7/rows.json?accessType=DOWNLOAD');
let data = await response.json()
return data;
}

async function getAccidentReportData() {
let response = await fetch('https://data.ct.gov/api/views/rybz-nyjw/rows.json?accessType=DOWNLOAD');
let data = await response.json()
return data;
}

async function getWeatherHistoryData() {
let response = await fetch('https://data.townofcary.org/api/v2/catalog/datasets/rdu-weather-history/exports/json');
let data = await response.json()
return data;
}

const getJsonData = ( isVisible, indexValue ) => {
if(isVisible === true && indexValue === 1) {
getHawaiiGovData().then((dataJson) => {
DataStore.data.index=indexValue;
DataStore.data.dataObject=dataJson;
console.log(dataJson);
});
}
else if(isVisible === true && indexValue === 2) {
getAccidentReportData().then((dataJson) => {
DataStore.data.index=indexValue;
DataStore.data.dataObject=dataJson;
console.log(dataJson);
});
}
else if(isVisible === true && indexValue === 4) {
//
getWeatherHistoryData().then((dataJson) => {
DataStore.data.index=indexValue;
DataStore.data.dataObject=dataJson;
console.log(dataJson);
});
}
}

const LinkComponent = ({ isVisible, indexValue }) => {
{console.log('div ' + indexValue + ' visibility is ' + isVisible)}
return (
<div >
<p><i>This is inner content for now, could be a link or a button that the user might click.</i></p>
{getJsonData(isVisible, indexValue)}

</div>);
}

export default class InnerContent extends Component {

static propTypes = {
/**
* Define if the visibility need to be tracked once
*/
index: PropTypes.number,
isVisible: PropTypes.bool
}

static defaultProps = {
index: 0,
isVisible: false
};

constructor(props) {
super(props);
this.ownProps = Object.keys(InnerContent.propTypes);
}

render() {
return (
<div className={'squarebox'}>
<p>This is content for {this.props.index}</p>
<LinkComponent isVisible={this.props.isVisible} indexValue={this.props.index}/>
</div>
);
}
}

I have taken the liberty to reference some open Json urls from the US government website — https://catalog.data.gov/

<Please don’t arrest me if this wasn’t allowed dear US Govt>

See the effect of scrolling on my site in the following screenshots..

As you can see that as the divs appeared in the viewport, the console displays the visibility of the current div being displayed and also asynchronously fetches data behind the scenes from the https://catalog.data.gov/ website

The div inner content could have been a link or a button that would swap out this component and render a new one in its place. (see the content within the divs in italics)

So essentially, even before you wait for the user to click, you eagerly fetch the data for the div being displayed and store it in the browser.

Actually, I wouldn’t recommend storing data in the browser unless it is a smaller size of data. The better thing to do would be to eagerly fetch this data and cache it server side so that when the fetch call is made, the data is fetched from the server side cache. Of course this wont solve the problem of latency but it will still avoid further hops that the server would have to make to fetch the data from further downstream/upstream systems.

But if you absolutely want your site to be on steroids and the data footprint is small, you can keep it client side in a Javascript object.

Best Practices

To achieved what we have talked about, you would ideally have to make some structural changes to your site.

  1. For components that you want to track visibility for, keep the components large so that less is visible in the viewport as you load the data in the background. This will ensure that you load less data in the background as you might just be displaying one or two of these components in the viewport at a point of time.
  2. Don’t do it for everything you display to the user. Use this feature where it is absolutely required and will not overload your client’s browser and slow his device down.
  3. Bear in mind, this will increase network traffic to the client as you are making preemptive fetch calls for data that the user might not even see. This might incur your client consuming their monthly quota of data if they are on a mobile. I would probably keep this feature configurable and let the user opt in for a better experience if they don’t care about the extra network calls.
  4. Pagination: Preferably combine this with a pagination feature. So essentially if the user is seeing a list and you have control over the ordering of the list, have the data paginated so that you can combine the preemptive fetch call with a paginated call to fetch a small amount of data up front. This approach would work perfectly for tables, lists etc on your site.
  5. Static data that is not likely to change such as Terms of use, headers, footers etc can preferably be pre-fetched this way.

I hope you found this article informative. I have found great use for the React on screen library to do a WYSWYL and I hope that you will too.

A Second disclaimer: I am by no means a React or Javascript expert. I am an enthusiast and in my fiddling with various Javascript frameworks and libraries I discovered this paradigm. So don’t burn me at the stake if you don’t agree with my views.. If you do please, do a like and subscribe. Oh wait.. this isn’t YouTube!

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

How to make an iframe automatically resize to fit its content

Top 3 Udemy Coding Teachers

Using laravel-echo-server with React Native

Haha.me | Made with Next JS

Haha.me | Made with Next JS

Agify: A mobile application powered by PhoneGap technology

Reactor — Handle Error

compose(...functions)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ritesh Shergill

Ritesh Shergill

More from Medium

How to create Nft on EOS

Introduction to React.js

React 18 vs React 17 — Batching Renders

How you can save up to 80% on the Gas fee? | Block miners’ dilemma