refactor: LoadingBar via progressbar.js + ref (drops react-progress-bar.js findDOMNode)

react-progress-bar.js (unmaintained wrapper) rendered the progress line
through findDOMNode. Reimplemented LoadingBar with progressbar.js directly
(the wrapper's own underlying dep) via a ref + useEffect — same thin line
(strokeWidth 2, #5A7636), no findDOMNode. Promoted progressbar.js to a
direct dependency and removed react-progress-bar.js. Verified progressbar.js
draws its SVG in-browser; findDOMNode gone from /fires and home; REST smoke
byte-identical.
This commit is contained in:
vjrj 2026-07-21 14:24:32 +02:00
parent 0abf5b4f02
commit b710388f50
3 changed files with 67 additions and 49 deletions

View file

@ -1,25 +1,46 @@
/* eslint-disable react/jsx-indent */ /* eslint-disable react/jsx-indent */
import React from 'react'; import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { Line } from 'react-progress-bar.js'; import ProgressBar from 'progressbar.js';
import './LoadingBar.scss'; import './LoadingBar.scss';
// Check: https://github.com/kimmobrunfeldt/react-progressbar.js/pull/26 // Uses progressbar.js directly through a ref, replacing the react-progress-bar.js
const LoadingBar = ({ progress }) => ( // wrapper (which relied on the deprecated findDOMNode).
<div className="loading-bar"> const LoadingBar = ({ progress }) => {
<Line const elRef = useRef(null);
progress={Meteor.status().status !== 'connected' ? Meteor.status().retryCount / 10 : progress} const barRef = useRef(null);
options={{ strokeWidth: 2, color: '#5A7636' }}
initialAnimate
/>
</div>
);
export default LoadingBar; const status = Meteor.status();
const target = status.status !== 'connected' ? status.retryCount / 10 : progress;
const clamped = Math.max(0, Math.min(1, target));
useEffect(() => {
barRef.current = new ProgressBar.Line(elRef.current, {
strokeWidth: 2,
color: '#5A7636'
});
return () => {
if (barRef.current) barRef.current.destroy();
barRef.current = null;
};
}, []);
useEffect(() => {
if (barRef.current) barRef.current.animate(clamped);
}, [clamped]);
return (
<div className="loading-bar">
<div ref={elRef} />
</div>
);
};
LoadingBar.propTypes = { LoadingBar.propTypes = {
progress: PropTypes.number.isRequired progress: PropTypes.number.isRequired
}; };
export default LoadingBar;

67
package-lock.json generated
View file

@ -55,6 +55,7 @@
"pm2-master": "^1.1.3", "pm2-master": "^1.1.3",
"popper.js": "^1.12.7", "popper.js": "^1.12.7",
"prerender-node": "^2.7.4", "prerender-node": "^2.7.4",
"progressbar.js": "^1.1.1",
"prop-types": "^15.6.0", "prop-types": "^15.6.0",
"push.js": "^1.0.5", "push.js": "^1.0.5",
"rc-slider": "^8.5.0", "rc-slider": "^8.5.0",
@ -71,7 +72,6 @@
"react-leaflet-google": "^3.2.1", "react-leaflet-google": "^3.2.1",
"react-mobile-store-button": "0.0.3", "react-mobile-store-button": "0.0.3",
"react-places-autocomplete": "^5.4.3", "react-places-autocomplete": "^5.4.3",
"react-progress-bar.js": "^0.2.3",
"react-resize-detector": "^1.1.0", "react-resize-detector": "^1.1.0",
"react-router-bootstrap": "^0.26.3", "react-router-bootstrap": "^0.26.3",
"react-router-dom": "^6.30.4", "react-router-dom": "^6.30.4",
@ -4310,11 +4310,6 @@
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
"integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
}, },
"node_modules/cheerio/node_modules/lodash.merge": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz",
"integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU="
},
"node_modules/chownr": { "node_modules/chownr": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@ -11450,12 +11445,6 @@
"resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
"integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4="
}, },
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
},
"node_modules/lodash.istypedarray": { "node_modules/lodash.istypedarray": {
"version": "3.0.6", "version": "3.0.6",
"resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz",
@ -11483,9 +11472,10 @@
"dev": true "dev": true
}, },
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
"version": "4.6.1", "version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"license": "MIT"
}, },
"node_modules/lodash.omit": { "node_modules/lodash.omit": {
"version": "4.5.0", "version": "4.5.0",
@ -19268,11 +19258,13 @@
} }
}, },
"node_modules/progressbar.js": { "node_modules/progressbar.js": {
"version": "1.0.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/progressbar.js/-/progressbar.js-1.0.1.tgz", "resolved": "https://registry.npmjs.org/progressbar.js/-/progressbar.js-1.1.1.tgz",
"integrity": "sha1-9/v8GVJA/guzL2972y5/9ADqcfk=", "integrity": "sha512-FBsw3BKsUbb+hNeYfiP3xzvAAQrPi4DnGDw66bCmfuRCDLcslxyxv2GyYUdBSKFGSIBa73CUP5WMcl6F8AAXlw==",
"license": "MIT",
"dependencies": { "dependencies": {
"shifty": "^1.5.2" "lodash.merge": "^4.6.2",
"shifty": "^2.8.3"
} }
}, },
"node_modules/prop-types": { "node_modules/prop-types": {
@ -19737,19 +19729,6 @@
"react": ">=0.14.7" "react": ">=0.14.7"
} }
}, },
"node_modules/react-progress-bar.js": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/react-progress-bar.js/-/react-progress-bar.js-0.2.3.tgz",
"integrity": "sha512-dyPLW0Wux9uOgEdz9xCtdeS/FD14KwygyW3dNLkogZ7GM1SMaI2yQ3uhQ0S/CyyPhtjAKWbH5XvzI0bnytDbxQ==",
"dependencies": {
"lodash.isequal": "^4.1.4",
"progressbar.js": "^1.0.1"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0",
"react-dom": "^15.0.0 || ^16.0.0"
}
},
"node_modules/react-resize-detector": { "node_modules/react-resize-detector": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-1.1.0.tgz", "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-1.1.0.tgz",
@ -20642,9 +20621,27 @@
"dev": true "dev": true
}, },
"node_modules/shifty": { "node_modules/shifty": {
"version": "1.5.4", "version": "2.20.4",
"resolved": "https://registry.npmjs.org/shifty/-/shifty-1.5.4.tgz", "resolved": "https://registry.npmjs.org/shifty/-/shifty-2.20.4.tgz",
"integrity": "sha1-1DYvyRTdKA3fblIr5AiyEgMgg0Y=" "integrity": "sha512-4Y0qRkg8ME5XN8yGNAwmFOmsIURGFKT9UQfNL6DDJQErYtN5HsjyoBuJn41ZQfTkuu2rIbRMn9qazjKsDpO2TA==",
"license": "MIT",
"optionalDependencies": {
"fsevents": "^2.3.2"
}
},
"node_modules/shifty/node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
}, },
"node_modules/shimmer": { "node_modules/shimmer": {
"version": "1.2.1", "version": "1.2.1",

View file

@ -55,6 +55,7 @@
"pm2-master": "^1.1.3", "pm2-master": "^1.1.3",
"popper.js": "^1.12.7", "popper.js": "^1.12.7",
"prerender-node": "^2.7.4", "prerender-node": "^2.7.4",
"progressbar.js": "^1.1.1",
"prop-types": "^15.6.0", "prop-types": "^15.6.0",
"push.js": "^1.0.5", "push.js": "^1.0.5",
"rc-slider": "^8.5.0", "rc-slider": "^8.5.0",
@ -71,7 +72,6 @@
"react-leaflet-google": "^3.2.1", "react-leaflet-google": "^3.2.1",
"react-mobile-store-button": "0.0.3", "react-mobile-store-button": "0.0.3",
"react-places-autocomplete": "^5.4.3", "react-places-autocomplete": "^5.4.3",
"react-progress-bar.js": "^0.2.3",
"react-resize-detector": "^1.1.0", "react-resize-detector": "^1.1.0",
"react-router-bootstrap": "^0.26.3", "react-router-bootstrap": "^0.26.3",
"react-router-dom": "^6.30.4", "react-router-dom": "^6.30.4",