Skip to content

Instantly share code, notes, and snippets.

@marceliwac
Created September 2, 2020 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marceliwac/cfa0705de7db0bb44901fcf48430720c to your computer and use it in GitHub Desktop.
Save marceliwac/cfa0705de7db0bb44901fcf48430720c to your computer and use it in GitHub Desktop.
The useLatestData hook with a bug that does not take into account updated path.
import React from 'react';
import {api} from '../data/store.js';
import config from "../config/config";
import ConnectionContext from "../contexts/ConnectionContext";
const Logger = require('@marceliwac/logger');
const refreshInterval = (1000 * config.dataRefreshIntervalInSeconds) || 10000;
async function newDataAvailable(checksumPath, currentChecksum){
Logger.debug('Checking if new data is available.');
try {
const response = await api(checksumPath);
if (response.status === 200) {
return response.data.checksum;
}
} catch(error) {
Logger.error('Could not fetch the latest checksum!', error);
throw error;
}
}
async function fetchData(endpoint) {
Logger.debug('Fetching latest data.');
try {
const pre = Date.now();
const response = await api(endpoint);
const post = Date.now();
Logger.debug('Fetching took: ' + (post-pre)/1000 + ' seconds.');
Logger.debug('Data fetched:', response.data);
if (response.status === 200) {
return response.data;
}
Logger.error('Could not retrieve data! API response code was not 200.');
} catch(error) {
Logger.error('Could not fetch the latest data!', error);
throw error;
}
}
function getQueryStringFromOptions(options) {
let queryString = '';
if(options
&& Object.prototype.hasOwnProperty.call(options, 'parameters')
&& Array.isArray(options.parameters)
&& options.parameters.length >= 1) {
queryString += '?';
options.parameters.forEach((parameter, index) => {
queryString += `parameters[]=${parameter}`;
if(index + 1 < options.parameters.length){
queryString += '&';
}
});
}
return queryString;
}
function getPathFromOptions(options) {
if(options
&& Object.prototype.hasOwnProperty.call(options, 'path')){
return options.path;
}
return '/';
}
function getChecksumPathFromOptions(options) {
if(options
&& Object.prototype.hasOwnProperty.call(options, 'checksumPath')){
return options.checksumPath;
}
return '/';
}
export default function useLatestData(options) {
const [data, setData] = React.useState(null);
const [currentChecksum, setCurrentChecksum] = React.useState(null);
const {isConnected} = React.useContext(ConnectionContext);
const queryString = getQueryStringFromOptions(options);
const path = getPathFromOptions(options);
const checksumPath = getChecksumPathFromOptions(options);
const refresh = Object.prototype.hasOwnProperty.call(options, 'refresh') ? options.refresh : false;
Logger.debug(`Data will ${(refresh ? '' : 'not ')}be automatically refreshed.`);
React.useEffect(() => {
async function update() {
if(isConnected) {
if(data === null){
const fetchedData = await fetchData(`${path}${queryString}`);
setData(fetchedData);
return;
}
const newCurrentChecksum = await newDataAvailable(checksumPath, currentChecksum);
if (currentChecksum !== newCurrentChecksum) {
setCurrentChecksum(newCurrentChecksum);
const fetchedData = await fetchData(`${path}${queryString}`);
setData(fetchedData);
}
}
}
update().catch((error) => {
Logger.error('Could not update or fetch the latest the data!', error);
});
if(refresh
&& options
&& Object.prototype.hasOwnProperty.call(options, 'checksumPath')) {
const interval = setInterval(update, refreshInterval);
return () => clearInterval(interval);
}
}, [checksumPath, currentChecksum, data, isConnected, options, options.checksumPath, path, queryString, refresh]);
return [data];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment